PHP设计模式——工厂方法

2019-11-06 18:58:04 浏览数 (1)

点击上方“Lemon黄”关注我哦,不定期原创文,定期好技术文推广分享

译者:Lemon黄 来源:https://www.startutorial.com/articles/view/understanding-design-patterns-factory-method

工厂方法:定义用于创建对象的接口,但是让实现该接口的类决定要实例化的类。 Factory方法允许类将实例化延迟到子类。

用了简单工厂(Simple Factory)的设计模式,开发人员现在可以在Dragon公司中享受他们的一天。尽管对玩具进行了详尽的讨论,但我们还没有真正研究过玩具类。 玩具类是具有功能prepare()package()label()的抽象类。

代码语言:javascript复制
//玩具抽象类
abstract class Toy
{
    public $name  = '';
    public $price  = 0;
 
    public function prepare()
    {
        echo $this->name. ' is prepared';
    }
 
    public function package()
    {
        echo $this->name. ' is packaged';
    }
 
    public function label()
    {
        echo $this->name . ' is priced at '.$this->price;
    }
}

具体的汽车(Car)类,直升机(Helicopter )类从抽象父类(Toy)继承而来,这两个具体的类实现代码很简单,如下:

Car类:

代码语言:javascript复制
class Car extends Toy
{
    public $name  = 'Car';
    public $price = 20;
}

Helicopter类:

代码语言:javascript复制
class Helicopter extends Toy
{
    public $name  = 'Helicopter';
    public $price = 100;
}

回到Dragon 公司。首席执行官带着微笑笑着走进开发商办公室,但我们知道有坏消息要来。 首席执行官高兴地宣布,Dragon Inc.将在美国开设几家工厂。 他们将位于不同的州,前两个工厂将在纽约和加利福尼亚。 所有玩具将在当地生产并拥有自己的属性,这意味着对于同类型的玩具车,在纽约生产的玩具将是NyCar,在加利福尼亚生产的玩具将是CaCar。 简单工厂模式(Simple Factory)将使开发团队轻松完成此任务。 他们所需要做的就是创建一个特定于位置的SimpleFactory类和一个特定于位置的ToysFactory类。 简单工厂(SimpleFactory)模式简化了任务,使开发人员的工作变得容易。

例如,对于纽约,我们可以这样做:

代码语言:javascript复制
//针对纽约 的简单工厂类
class NySimpleFactory
{
 
    public function createToy($toyName)
    {
        $toy = null;
        if ('car'==$toyName) {
            $toy = new NyCar();
        } else if ('helicopter'==$toyName) {
            $toy = new NyHelicopter();
        }
        return $toy;
    }
}

//针对纽约 的玩具工厂类
class NyToysFactory
{
    public $simpleFactory;
 
    public function __construct(SimpleFactory $simpleFactory)
    {
        $this->simpleFactory = $simpleFactory;
    }
 
    public function produceToy($toyName)
    {
        $toy = null;
        $toy = $this->simpleFactory->createToy($toyName);
        $toy->prepare();
        $toy->package();
        $toy->label();
        return $toy;
    }
}

开发人员可以迅速完成新代码,并将其移交给美国工厂。 两周后,由于纽约工厂出现生产问题,电话开始在开发人员办公室响起。 事实证明,NyToysFactory类已由远程分支的开发人员修改,因为那里的员工不想执行包装和标签工作。 他们通过删除label()package()函数来修改了produceToy()函数。

在这种情况下,简单工厂(SimpleFactory)模式似乎无法正常工作。 我们不希望美国的分支机构能够修改produceToy()函数。 produceToy()应该包含一组标准过程,并且分支机构仅应负责创建特定于位置的玩具。 如果他们可以创建一个抽象类怎么办? 他们创建的抽象类将具有一个具体的produceToy()方法,该方法将实现所有分支必须遵循的一组标准操作过程。 在produceToy()内部,它调用自己的抽象方法createToy()来获得玩具对象。 这种方式createToy()能够封装对象的创建,并且由于它是抽象的,因此将创建委托给其子类。

这听起来完全符合他们的要求:

代码语言:javascript复制
abstract class ToysFactory
{
    public function produceToy($toyName)
    {
        $toy = null;
        $toy = $this->createToy($toyName);
        $toy->prepare();
        $toy->package();
        $toy->label();
        return $toy;
    }
 
    abstract public function createToy($toyName);
}

现在在纽约分支中,他们所需要做的就是在子类中实现createToy()方法:

代码语言:javascript复制
class NyToysFactory extends ToysFactory
{
 
    public function createToy($toyName)
    {
        $toy = null;
        if ('car'==$toyName) {
            $toy = new NyCar();
        } else if ('helicopter'==$toyName) {
            $toy = new NyHelicopter();
        }
        return $toy;
    }
 
}

对于加利福尼亚的工厂,他们必须创建另一个子类CaToyFactory才能在本地生产玩具:

代码语言:javascript复制
class CaToysFactory extends ToysFactory
{
    public function createToy($toyName)
    {
        $toy = null;
        if ('car'==$toyName) {
            $toy = new CaCar();
        } else if ('helicopter'==$toyName) {
            $toy = new CaHelicopter();
        }
        return $toy;
    }
}

在上面的代码中,ToysFactory类中的函数createToy()被称为工厂方法。 工厂方法模式定义用于创建对象的接口(createToy)。 但是它将实际的创建委托给子类(NyToysFactoryCaToyFactory)。 这样子类可以决定要创建的对象。

0 人点赞