首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP抽象工厂模式实现

PHP抽象工厂模式实现
EN

Stack Overflow用户
提问于 2015-01-05 18:18:42
回答 2查看 1.7K关注 0票数 0

我正在阅读关于不同模式的文章。目前,我在抽象工厂模式,我认为我有相当好的把握它。我的资源除了维基百科:pattern.htm http://www.oodesign.com/abstract-factory-pattern.html https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/AbstractFactory

我正在使用苹果及其产品制作一个示例抽象工厂模式作为一个例子。我知道代码复制是糟糕的设计,因此我写这篇文章。到目前为止我的代码是:

代码语言:javascript
复制
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 */}
}

等等,这里的代码太多了。我知道,最好在目录和名称空间中进行组织。这不是我现在学到的。我正在学习模式和面向对象的概念。

有关的一节是:

代码语言:javascript
复制
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().我做的是抽象工厂模式对吗?再说一遍,“代码复制是糟糕的设计!”有什么更好的方法来解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-05 19:20:15

我觉得你犯了个大错。抽象工厂的目的是为产品族的创建创建一个抽象,这样您就可以轻松地将其转换为不同的家族。f.e.(苹果=>三星:)

代码语言:javascript
复制
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 {}

...

当您想在两家公司之间切换时,使用抽象工厂模式是有意义的。您的代码应该只依赖抽象(坚实的原则) ComputerAbstractFactory、平板电脑、电话和计算机。如果你决定的话,请这样做。(通过一些配置开关)应该使用哪一家制造商--如果您将ComputerAbstractFactory的选择实现注入到您的业务代码中,那么您就完成了--一切都正常工作,平板电脑被创建,手机等等

您需要决定要在应用程序中创建什么抽象,这样调用代码就不会耦合到该抽象的具体实现中。我相信IPlayer是您想要的,其中IPodClassic IPodShuffle是具体的实现。如果我是对的,你应该创建IPlayerFactory

代码语言:javascript
复制
class IPlayerFactory {
    /**
    * @return IPlayer
    */
    function create() {...}
}

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

票数 3
EN

Stack Overflow用户

发布于 2015-01-05 18:36:01

你在正确的道路上,但我认为你的界面是错误的。

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

这将是我的解决方案:

代码语言:javascript
复制
<?php
interface AppleFactoryInterface
{
    function create($data);
}

下面是一个iPhoneFactory:

代码语言:javascript
复制
<?php
class iPhoneFactory implements AppleFactoryInterface
{
    public function create($data)
    {
        $klass = sprintf('iPhone'.$data['type']);
        $instance = new $klass;
        $instance->setFromArray($data);

        return $instance;
    }
}

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27785474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档