深入PHP面向对象、模式与实践——生成对象(3)

原型模式

平行继承层次的出现是工厂方法模式带来的一个问题。一个避免这种依赖的方法是使用PHP的clone关键词复制已存在的具体产品。然后,具体产品类本身便成为它们自己生成的基础。这便是原型模式。使用该模式我们可以用组合代替继承。这样的转变促使了代码运行时的灵活性,并减少了必须创建的类。

以下展示一个抽象工厂和工厂方法模式的类图:
这里写图片描述

你可以看到,我们依赖继承来组合工厂生成terrain家族产品,但这需要一个大型的继承体系,并且相对来说不那么灵活。当你不想平行的继承体系而需要最大化运行时的灵活性时,可以使用抽象工厂模式的强大变形——原型模式。

  • 实现

简单地创建一个保存具体产品的工厂类,并在初始化时就加入这种做法。

class Sea
{
}

class EarthSea extends Sea
{
}

class MarsSea extends Sea
{
}

class Plains
{
}

class EarthPlains extends Plains
{
}

class MarsPlains extends Plains
{
}

class Forest
{
}

class EarthForest extends Forest
{
}

class MarsForest extends Forest
{
}

class TerrainFactory
{
    private $sea;
    private $forest;
    private $plains;

    public function __construct(Sea $sea, Plains $plains, Forest $forest)
    {
        $this->sea = $sea;
        $this->forest = $forest;
        $this->plains = $plains;
    }

    public function getSea()
    {
        return clone $this->sea;
    }

    public function getForest()
    {
        return clone $this->forest;
    }

    public function getPlains()
    {
        return clone $this->plains;
    }
}

$factory = new TerrainFactory(new EarthSea(), new EarthPlains(), new EarthForest());
print_r($factory->getSea());

可以看到,我们加载了一个带有产品对象实例的具体的TerrainFactory对象。当客户端代码调用getSea()时返回在初始化时缓存的Sea对象的一个副本。我们不仅仅省掉了一些类,还增加额外的灵活性。如创建一个有类似地球海洋和森林以及火星平原的星球:

$factory = new TerrainFactory(new EarthSea(), new MarsPlains(), new EarthForest());

因此原型模式使我们可利用组合所提供的灵活性,不过我们得到的可不止这个。因为在运行时保存和克隆对象,所以当生成新产品时,可以重新设定对象状态。

class Sea
{
    private $navigability = 0;

    function __construct($navigability)
    {
        $this->navigability = $navigability;
    }
}

要记住但是如果产品对象引用了其他对象,那你应该实现__clone()方法来保证你得到的是深复制。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值