zoukankan      html  css  js  c++  java
  • php 设计模式之抽象工厂模式

    抽象工厂模式(Abstact Factory)是一种常见的软件设计模式。该模式为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以为此系列的产品族创建一个具体的工厂类。
    一、意图
    抽象工厂模式提供一个创建一系统相关或相互依赖对象的接口,而无需指定它们具体的类【GOF95】
    二、抽象工厂模式结构图

    三、结合一个简单的例子了解

    用种蔬菜的例子来说明事实,最初的时候,由于规模小,只种植一种蔬菜,根菜类蔬菜,这个时候由于种植方式比较简单,采用简单工厂模式即可,主要目的是让工人轻松,下达工厂种植即可,但是随着种植厂的发展以及市场的需求,要增加一种蔬菜类型种植了,茎菜,由于茎菜与根菜种植方式不一致,就需要两个专门的种植工厂来进行管理,那么久采用工厂模式来管理,一个工厂负责一种作物的种植,这个时候产品可以理解为仍然在一个层次。但是随着科技的发展,我们逐步要种植转基因与非转基因食品了,在以前的蔬菜种类上又增加了一个层次,这个时候无法将其作为一个层次来解决,所以必须采用抽象工厂的方式来解决。我用UML图表示三种结构:

     

    • 上面的UML图很明显的就看出来了,抽象工厂可以创建多个产品类对象,如在种菜工厂中,有种根菜,种茎菜。工厂模式与抽象工厂模式以及简单工厂模式只有在具体应用的时候,分析具体的产品层级,然后选择相应的设计模式。
    • 而在每一个层次,种菜工人所关心的对象也不一样,在简单工厂模式下,工人要想到种植萝卜还是白菜,在工厂模式下,工人想到是种植根菜还是茎菜,而在抽象工厂模式下,则关心种植基因菜还是非基因菜

    四、抽象工厂模式中主要角色

    抽象工厂(Abstract Factory)角色:它声明一个创建抽象产品对象的接口。通常以接口或抽象类实现,所有的具体工厂类必须实现这个接口或继承这个类。
    具体工厂(Concrete Factory)角色:实现创建产品对象的操作。客户端直接调用这个角色创建产品的实例。这个角色包含有选择合适的产品对象的逻辑。通常使用具体类实现。
    抽象产品(Abstract Product)角色:声明一类产品的接口。它是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
    具体产品(Concrete Product)角色:实现抽象产品角色所定义的接口,定义一个将被相应的具体工厂创建的产品对象。其内部包含了应用程序的业务逻辑。
    五、抽象工厂模式的优缺点
    抽象工厂模式的优点:
    1、分离了具体的类
    2、使增加或替换产品族变得容易
    3、有利于产品的一致性
    抽象工厂模式的缺点: 难以支持新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新各类的产品就需要扩展访工厂接口,从而导致AbstractFactory类及其所有子类的改变。
    抽象工厂就是以一种倾斜的方式支持增加新的产品中,它为新产品族的增加提供了方便,而不能为新的产品等级结构的增加提供这样的方便。
    六、抽象工厂模式适用场景
    以下情况应当使用抽象工厂模式:
    1、一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
    2、这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
    3、 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
    4、系统提供一个产品类的库,所有的产品以同样的接口出现,从而使用客户端不依赖于实现
    七、抽象工厂模式与其它模式
    单例模式(singleton模式):具体工厂类可以设计成单例类,由于工厂通常有一个就可以,因此具体工厂子类一般都实现为一个Singleton。
    工厂方法模式(factory method模式):抽象工厂创建产品的方法定义为工厂方法。
    原型模式(prototype模式):如果有多个可能的产品系列,具体的工厂也可以使用原型模式,具体工厂使用产品系列中
    每一个产品的原型进行实例化并且通过复制它的原型来创建新的产品。

    八、抽象工厂模式PHP示例

    <?php
    /**
     * 抽象产品A
     */
    interface AbstractProductA {
    
        /**
         * 取得产品名
         */
        public function getName();
    }
    
    /**
     * 抽象产品B
     */
    interface AbstractProductB {
    
        /**
         * 取得产品名
         */
        public function getName();
    }
    
    /**
     * 具体产品A1
     */
    class ProductA1 implements AbstractProductA {
        private $_name;
    
        public function __construct() {
            $this->_name = 'product A1';
        }
    
        public function getName() {
            return $this->_name;
        }
    }
    
    
    /**
     * 具体产品A2
     */
    class ProductA2 implements AbstractProductA {
        private $_name;
    
        public function __construct() {
            $this->_name = 'product A2';
        }
    
        public function getName() {
            return $this->_name;
        }
    }
    
    
    /**
     * 具体产品B1
     */
    class ProductB1 implements AbstractProductB {
        private $_name;
    
        public function __construct() {
            $this->_name = 'product B1';
        }
    
        public function getName() {
            return $this->_name;
        }
    }
    
    /**
     * 具体产品B2
     */
    class ProductB2 implements AbstractProductB {
        private $_name;
    
        public function __construct() {
            $this->_name = 'product B2';
        }
    
        public function getName() {
            return $this->_name;
        }
    }
    /**
     * 抽象工厂
     */
    interface AbstractFactory {
        /**
         * 创建等级结构为A的产品的工厂方法
         */
        public function createProductA();
    
        /**
         * 创建等级结构为B的产品的工厂方法
         */
        public function createProductB();
    
    }
    
    /**
     * 具体工厂1
     */
    class ConcreteFactory1 implements AbstractFactory{
    
        public function createProductA() {
            return new ProductA1();
        }
    
        public function createProductB() {
            return new ProductB1();
        }
    }
    
    
    /**
     * 具体工厂2
     */
    class ConcreteFactory2 implements AbstractFactory{
    
        public function createProductA() {
            return new ProductA2();
        }
    
        public function createProductB() {
            return new ProductB2();
        }
    }
    
    
    
    
    /**
     * 客户端
     */
    class Client {
    
        /**
         * Main program.
         */
        public static function main() {
            self::run(new ConcreteFactory1());
            self::run(new ConcreteFactory2());
        }
    
        /**
         * 调用工厂实例生成产品,输出产品名
         * @param $factory AbstractFactory 工厂实例
         */
        public static function run(AbstractFactory $factory) {
            $productA = $factory->createProductA();
            $productB = $factory->createProductB();
            echo $productA->getName(), '<br />';
            echo $productB->getName(), '<br />';
        }
    
    }
    
    Client::main();

    //打印数据
    //product A1
    //product B1
    //product A2
    //product B2
    ?>
  • 相关阅读:
    B
    C. Baby Ehab Partitions Again
    NLP中数据稀疏问题的解决——数据平滑
    CodeForces-EDU-105 Div2 部分题解报告
    C
    前端面试知识点汇总
    elementUI table 合计行 单元格合并
    微信小程序 tab切换组件封装
    微信小程序-wx.request的封装实现
    微信小程序-input密码可见与不可见
  • 原文地址:https://www.cnblogs.com/dawuge/p/13495415.html
Copyright © 2011-2022 走看看