UML类图工厂方法模式依赖于继承,因为对象创建 委托给 实现工厂方法创建对象 的子类
在上面的URL类图中,Creator
需要 Product
对象的 Product1
类不直接实例化类。相反,它 Creator
指的是单独 factoryMethod()
创建一个产品对象,这使得Creator
独立于哪个具体类被实例化。Creator
可以重新定义要实例化的类的子类。在这个例子中,Creator1
子类factoryMethod()
通过实例化类来实现抽象Product1
。
上面简述一个工厂工作的流程,重点请看下面
1. 简单工厂模式
-
模式定义:
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,之所以可以这么说,是因为简单工厂模式是通过一个静态方法来创建对象的。它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。 - 模式结构
- Factory:工厂角色
工厂角色负责实现创建所有实例的内部逻辑
- Product:抽象产品角色
抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
- ConcreteProduct:具体产品角色
具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
举个栗子
我们想创建一个工厂,这个工厂呢可以生产猫和狗!通常情况下我们会怎么做呢
interface animals // 抽象产品角色
{
public function animal();
}
class Cat implements animals // 具体产品角色
{
public function animal()
{
return "猫猫";
}
}
class Dog implements animals // 具体产品角色
{
public function animal()
{
return "狗狗";
}
}
class Factory // 工厂角色
{
public static function createAnimal($param)
{
$result = null;
switch($param)
{
case 'cat':
$result = new Cat();
break;
case 'dog':
$result = new Dog();
break;
}
return $result;
}
}
echo Factory::createAnimal("cat")->animal(); // 猫猫
echo Factory::createAnimal("dog")->animal(); // 狗狗
上面的例子中所讲到的就是 简单工厂(静态工厂) <还请大佬批评>
简单工厂适用环境
- 工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
- 客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。
2. 工厂方法模式
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
举个栗子:
abstract class animals // 抽象产品类
{
abstract public function animal();
}
class Cat extends animals // 具体产品类
{
public function animal()
{
return "猫猫";
}
}
class Dog extends animals // 具体产品类
{
public function animal()
{
return "狗狗";
}
}
interface Factory // 抽象工厂类, 将对象的创建抽象成一个接口
{
public function create();
}
class CatFactory implements Factory // 继承工厂类, 用于实例化产品
{
public function create()
{
return new Cat();
}
}
class DogFactory implements Factory // 继承工厂类, 用于实例化产品
{
public function create()
{
return new Dog();
}
}
class Client // 具体操作类
{
public function test()
{
$catResult = new CatFactory();
echo $catResult->create()->animal();
$DogResult = new DogFactory();
echo $DogResult->create()->animal();
}
}
$lala = new Client();
$lala->test(); // 猫猫狗狗
定义一个用于创建对象的接口,让子类决定哪个类实例化。 他可以解决简单工厂模式中的封闭开放原则问题。
【工厂方法模式与简单工厂模式】
- 工厂方法模式与简单工厂模式再结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
- 工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。
- 当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了”开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。
- 工厂方法模式退化后可以演变成简单工厂模式。
3. 抽象工厂模式
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
interface AnimalsFactory // 抽象工厂
{
public function createCat(); // 生产一尾猫
public function createDog(); // 生产一头狗 -_-
}
abstract class Cat // 猫抽象
{
abstract function getCat();
}
class ForeignCat extends Cat // 猫具体
{
public function getCat()
{
return "外国布偶猫".PHP_EOL;
}
}
class ChineseCat extends Cat
{
public function getCat()
{
return "华夏猫".PHP_EOL;
}
}
abstract class Dog
{
abstract function getDog();
}
class ChineseDog extends Dog
{
public function getDog()
{
return "中华国犬".PHP_EOL;
}
}
class ForeignDog extends Dog
{
public function getDog()
{
return "外国哈士奇".PHP_EOL;
}
}
class CreateChineseAnimalFactory implements AnimalsFactory
{
public function createCat()
{
return new ChineseCat();
}
public function createDog()
{
return new ChineseDog();
}
}
class CreateForeignAnimalFactory implements AnimalsFactory
{
public function createCat()
{
return new ForeignCat();
}
public function createDog()
{
return new ForeignDog();
}
}
$result = new CreateForeignAnimalFactory();
$ForeignCat = $result->createCat();
echo $ForeignCat->getCat(); // 布偶猫
$ForeignDog = $result->createDog();
echo $ForeignDog->getDog(); // 哈士奇
总结
区别
-
简单工厂模式(静态方法工厂模式) : 用来生产同一等级结构中的任意产品。(不能增加新的产品)
-
工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
-
抽象工厂 :用来生产不同产品种类的全部产品。(不能增加新的产品,支持增加产品种类)
结语
使用工厂模式的好时机并不总是显而易见的。不要强制这样做,只有在构建复杂系统时才需要进行大量的抽象。你只要知道什么是抽象工厂,迟早你会发现一个真正的用例。good luck!
写于2018年5月25日
网友评论