PHP抽象工厂模式实现

时间:2015-01-05 18:18:42

标签: php oop design-patterns abstract-factory

我正在阅读那里可用的不同模式。目前我处于抽象工厂模式,我认为我对它有很好的把握。我的资源是,除了维基百科: http://www.tutorialspoint.com/design_pattern/abstract_factory_pattern.htm http://www.oodesign.com/abstract-factory-pattern.html https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/AbstractFactory

我正在使用Apple及其产品制作抽象工厂模型示例作为示例。我知道代码重复是糟糕的设计,因此我写这个的原因。到目前为止我的代码是:

abstract class AbstractAppleFactory {
    abstract public function createiPod( $capacity, $type, $color, $engraving );
    abstract public function createiPhone( $capacity, $type, $color, $antenna );
    abstract public function createComputer( $type, $HDCapacity, $CPU, $ram );
}

class iPodFactory extends AbstractAppleFactory {
    public function createiPod( $capacity, $type, $color, $engraving ) {
        $class = 'iPod' . $type;

        return new $class( $capacity, $color, $engraving);
    }

    public function createiPhone( $capacity, $type, $color, $antenna ){ /* no implementation necessary */}
    public function createComputer( $type, $HDCapacity, $CPU, $ram ){ /* no implementation necessary */}
}

interface iPlayer {
    public function play();
    public function stop();
    public function fastForward();
    public function rewind();
}

abstract class iPod implements iPlayer {
    protected $capacity;
    protected $color;
    protected $engraving;

    public function __construct( $capacity, $color, $engraving = null ) {
        $this->capacity = $capacity;
        $this->color = $color;
        $this->engraving = $engraving;
    }
}

class iPodClassic extends iPod {
    public function play() {/* implementation goes here */}
    public function stop() {/* implementation goes here */}
    public function fastForward() {/* implementation goes here */}
    public function rewind() {/* implementation goes here */}
}
class iPodShuffle extends iPod {
    public function play() {/* implementation goes here */}
    public function stop() {/* implementation goes here */}
    public function fastForward() {/* implementation goes here */}
    public function rewind() {/* implementation goes here */}
}

等。等等。这里有太多的代码。我知道在目录和名称空间中组织起来会更好。这不是我现在正在学习的东西。我正在学习模式和OOP概念。

有问题的部分是:

class iPodFactory extends AbstractAppleFactory {
    public function createiPod( $capacity, $type, $color, $engraving ) {
        $class = 'iPod' . $type;

        return new $class( $capacity, $color, $engraving);
    }

    public function createiPhone( $capacity, $type, $color, $antenna ){ /* no implementation necessary */}
    public function createComputer( $type, $HDCapacity, $CPU, $ram ){ /* no implementation necessary */}
}

由于继承/抽象,我被迫在不相关的工厂中实现两个不必要的方法。 createiPhone()createComputer()。我在做抽象工厂模式吗?再次,"代码重复是糟糕的设计!"有什么更好的方法可以解决这个问题?

2 个答案:

答案 0 :(得分:3)

我认为你犯了一个重大错误。抽象工厂的目的是为了创建产品系列的创建抽象,因此您可以轻松地将其更改为不同的系列。 F.E. Apple =>三星:)

interface ComputerAbstractFactory {
    /**
    * @return Tablet
    */
    function createTablet();
    /**
    * @return Phone
    */
    function createPhone();
    /**
    * @return Computer
    */
    function createComputer();
}

class AppleComputerFactory implements ComputerAbstractFactory {}

class SamsungComputerFactory implements ComputerAbstractFactory {}

class IPad implements Tablet {}

class GalaxyTab implements Tablet {}

...

当您想要在两家公司之间切换时,使用抽象工厂模式是有意义的。 您的代码应仅依赖于抽象(SOLID原则)ComputerAbstractFactory,Tablet,Phone,Computer。 这样,如果你决定(通过一些配置切换)应该使用哪个制造商,那么你应该将选择的ComputerAbstractFactory实现注入到你的业务中 代码,你完成了 - 一切正常,平板电脑创建,手机等

您需要确定要在应用程序中创建的抽象,以便调用代码不会与该抽象的具体实现相关联。我相信IPlayer是你想要的,其中IPodClassic IPodShuffle是具体的实现。 如果我是对的,你应该创建IPlayerFactory

class IPlayerFactory {
    /**
    * @return IPlayer
    */
    function create() {...}
}

关于您提到的重复。如果iPodFactory扩展了AbstractAppleFactory,它应该实现它的所有方法(顺便说一句,如果AbstractAppleFactory没有任何实现它应该是一个接口) 你从SOLID原则中打破了Liskov原则。简短版本 - 如果调用代码依赖于AbstractAppleFactory并且它将iPodFactory作为操作的具体实现,它将在调用createiPhone或createComputer时中断 - 因此抽象在这种情况下不起作用。

答案 1 :(得分:0)

你是正确的方式,但我认为你的界面是错误的。

首先,除非您需要创建将在子类上使用的方法,否则不要使用abstract类。使用interface会更好。

这将是我的解决方案:

<?php
interface AppleFactoryInterface
{
    function create($data);
}

这是一个iPhoneFactory:

<?php
class iPhoneFactory implements AppleFactoryInterface
{
    public function create($data)
    {
        $klass = sprintf('iPhone'.$data['type']);
        $instance = new $klass;
        $instance->setFromArray($data);

        return $instance;
    }
}

正如您所看到的,我有更少的代码可以更好地理解。