工厂模式之工厂方法模式-创建型

在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

具有完整的产品接口、产品实现、工厂接口、工厂实现。

VS 简单工厂

  • 简单工厂包含了必要的逻辑判断,根据客户端参数,在工厂内部动态实例化类。有违“开闭原则”

  • 工厂方法通过增加一个具体工厂实现和具体产品实现。而简单工厂需要修改工厂实现

  • 客户端都需要修改代码,简单工厂需要修改参数,而工厂方法需要修改要使用哪个工厂

优点

  • 工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

  • 在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。

  • 在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,也无须修改其他的具体工厂和具体产品,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

缺点

  • 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有很多的类需要编译和运行,会给系统带来一些额外的开销。

  • 需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

适用

  • 在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。

* 在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

应用

Java JDBC

示例

<?php
/**
 * Interface Part
 */
interface Part
{
    public function produce();
}

/**
 * Class CarEngine
 */
class Engine implements Part
{
    public function produce()
    {
        echo '生产发动机';
        echo PHP_EOL;
    }
}

/**
 * Class CarWheel
 */
class Wheel implements Part
{
    public function produce()
    {
        echo '生产车轮';
        echo PHP_EOL;
    }
}

/**
 * Interface PartFactory
 */
interface PartFactory
{
    public function create();
}

/**
 * Class CarFactory
 */
class WheelFactory implements PartFactory
{
    public function create()
    {
        return new Wheel();
    }
}

/**
 * Class EngineFactory
 */
class EngineFactory implements PartFactory
{
    public function create()
    {
        return new Engine();
    }
}

$wheelFactory = new WheelFactory();
$wheel = $wheelFactory->create();
var_dump($wheel);
$wheel->produce();

$engineFactory = new EngineFactory();
$engine = $engineFactory->create();
var_dump($engine);
$engine->produce();

输出:

object(Wheel)#2 (0) {
}
生产车轮
object(Engine)#4 (0) {
}
生产发动机