工厂方法模式

工厂方法模式也会被简称为工厂模式,是简单工厂模式的升级版。那么,简单工厂模式存在什么问题呢?答案是违反了软件设计中的开闭原则

简单工厂模式存在什么问题

思考一个问题:在简单工厂模式的基础上,如果现在需要新增加产品 C,需要怎么改代码?

  1. 新增 ConcreteProductC 类,实现 Product
  2. 更改 Creator 类中的 createProduct 类。

修改后的代码如下:

<?php
 
class Creator
{
public function createProduct(string $type): Product
{
switch ($type) {
case 'A':
return new ConcreteProductA();
case 'B':
return new ConcreteProductB();
case 'C':
return new ConcreteProductC();
default:
throw new Exception('not found product');
}
}
}
 
abstract class Product
{
}
 
class ConcreteProductA extends Product
{
}
 
class ConcreteProductB extends Product
{
}
 
class ConcreteProductC extends Product
{
}
 
$creator = new Creator();
$creator->createProduct('A');

这不是挺好的吗,没啥问题。所以问题在哪?

问题就在于,在软件开发中,需要遵守开闭原则,“更改 Creator 类中的 createProduct 类”这一举动,违反了开闭原则,这就是问题所在。为了解决这个问题,引入了工厂方法模式。

当然,如果不遵守开闭原则,就无事发生。

UML 类图

2024010714103770.png

代码

<?php
 
abstract class Creator
{
abstract public function createProduct(string $type): Product;
}
 
class ConcreteCreatorA extends Creator
{
public function createProduct(string $type): Product
{
return new ConcreteProductA();
}
}
 
class ConcreteCreatorB extends Creator
{
public function createProduct(string $type): Product
{
return new ConcreteProductB();
}
}
 
 
abstract class Product
{
}
 
class ConcreteProductA extends Product
{
}
 
class ConcreteProductB extends Product
{
}
 
$creator = new ConcreteCreatorA();
$creator->createProduct('A');

新增产品 C

在此基础上,如果新增产品 C,需要这样做:

  1. 新增 ConcreteCreatorC 类,实现 Creator
  2. 新增 ConcreteProductC 类,实现 Product
<?php
 
abstract class Creator
{
abstract public function createProduct(): Product;
}
 
class ConcreteCreatorA extends Creator
{
protected function createProduct(): Product
{
return new ConcreteProductA();
}
}
 
class ConcreteCreatorB extends Creator
{
protected function createProduct(): Product
{
return new ConcreteProductB();
}
}
 
class ConcreteCreatorC extends Creator
{
protected function createProduct(): Product
{
return new ConcreteProductC();
}
}
 
 
abstract class Product
{
}
 
class ConcreteProductA extends Product
{
}
 
class ConcreteProductB extends Product
{
}
 
class ConcreteProductC extends Product
{
}
 
$creator = new ConcreteCreatorA();
$creator->createProduct();

可以看到,只是新增了两个类,就实现了需求。并没有更改原有代码,符合开闭原则

需要注意的是,上述的抽象类 CreatorProduct,也可以用接口来代替。