现在的位置: 首页 > 综合 > 正文

设计模式 – 抽象工厂模式

2018年04月07日 ⁄ 综合 ⁄ 共 2639字 ⁄ 字号 评论关闭

1. 意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

别名 Kit

设计模式一书中这个模式作为创建型模式的第一个模式出现,但是这个模式本身和Singleton(单例), Factory Method(工厂方法) 又有一定的关联性,所以建议可以先看这个模式,在看完单例和工厂方法模式后再回头看一遍抽象工厂会比较好。

重点在于“一系列“这三个字,同时这些对象是”相关或相互依赖的“,作者举了一个多视感标准的用户界面工具包的例子,光从意图的字面含义上就很容易能够理解这个模式的用途,一个用户界面工具包包含了很多种控件(组件),这些组件有一定的风格(Style)因此他们是相关的,抽象工厂定义了一个抽象的接口去创建他们,从调用者的角度来讲很好的满足了依赖倒置原则。

2. 适用性

在以下情况可以使用Abstract Factory模式

一个系统要独立于它的产品的创建,组合和表示时

一个系统要由多个产品系列中的一个来配置时

当你要强调一系列相关的产品对象的设计以便进行联合使用时

当你提供一个产品类库,而只想显示它们的接口而不是实现时

这部分内容很好的反映了抽象工厂与其他模式之间的区别,第一是使用某个产品系列来配置系统,第二产品系列里的产品对象需要联合使用

我突然想到一个问题:如果有一个支持多数据库的系统,数据访问层的设计为什么无法用到抽象工厂?

SqlConnection, SqlCommand, SqlParameter, SqlAdapter可以认为是一系列相关的类,但是我们很难说用这些类去“配置”一个系统

有一些场景倒是和产品系列和配置有点相关,例如

装修一个房子,有中式和西式两种风格,对应不同的风格墙面的颜色,吊顶的设计,瓷砖的选择,厨房卫生间的整体风格都要一致,每部分的选材可以认为是一系列相关的对象,同时他们一起可以装饰(配置)我的房子

另一个例子是电脑的组装,电脑是系统,其中的零配件是具体的产品,而诸如“家用型电脑”,“商务办公型”,"游戏娱乐型“ 可以认为是不同的产品系列(ConcreteFactory)

3. 结构

4. 效果

在看具体代码前先看下设计模式一书中的概括

1) 它分离了具体的类

2)它使得易于交换产品系列

3)它有利于产品的一致性

4)难以支持新种类的产品

5. 实现

根据抽象工厂的特点,很容易想到将具体工厂实现为一个单例

另外在创建具体产品类时,可以采用简单工厂方法(Simple Factory)

    class Program
    {
        static void Main(string[] args)
        {
            AbstractFactory factory = AbstractFactory.Instance("1");
            AbstractProductA productA = factory.CreateProductA();
            AbstractProductB productB = factory.CreateProductB();
            //call product a and product b methods to do something
        }
    }

    class FactoryConfig
    {
        public static int type;
    }

    abstract class AbstractFactory
    {
        private static AbstractFactory _instance = null;

        public abstract AbstractProductA CreateProductA();
        public abstract AbstractProductB CreateProductB();

        protected AbstractFactory()
        { 
        }

        public static AbstractFactory Instance()
        {
            if (_instance == null)
            {
                if (FactoryConfig.type == 1)
                    _instance = new ConcreteFactory1();
                else if (FactoryConfig.type == 2)
                    _instance = new ConcreteFactory2();
                else
                    throw new NotImplementedException();
            }
            return _instance;
        }
    }

    class ConcreteFactory1 : AbstractFactory
    {
        public override AbstractProductA CreateProductA()
        {
            return new ProductA1();
        }

        public override AbstractProductB CreateProductB()
        {
            return new ProductB1();
        }
    }

    class ConcreteFactory2 : AbstractFactory
    {
        public override AbstractProductA CreateProductA()
        {
            return new ProductA2();
        }

        public override AbstractProductB CreateProductB()
        {
            return new ProductB2();
        }
    }

    abstract class AbstractProductA
    { 
    }

    abstract class AbstractProductB
    { 
    }

    class ProductA1 : AbstractProductA
    { 
    }

    class ProductA2 : AbstractProductA
    { 
    }

    class ProductB1 : AbstractProductB
    { 
    }

    class ProductB2 : AbstractProductB
    { 
    }

注意上面的例子中 AbstractFactory类实现了一个单例,Instance 方法内部根据某个全局变量去创建ConcreteFactory

6. 缺点

很明显,当有新的产品系列出现时这个结构无法满足开放封闭原则

通俗的说就是当我们有中式,西式的装修风格,如果增加一种宫廷式装修风格那么势必增加很多类并且修改AbstractFactory

设计模式一书提出了可扩展的抽象工厂,个人认为这不是一个好主意(当然你可以通过传参数通过反射来实现)

设计无法做到完美,虽然增加产品系列会导致一系列的变化,但是好处是这个变化本身必须遵循这套结构,本质上不会增加什么复杂度,所以不必苛求

7. 扩展

上面的例子具体产品的对象创建没有用到工厂方法(Factory Method),既然抽象工厂涉及到的一系列产品是相关的,那么他们的创建也许就不像上面代码那样那么简单了

对于复杂对象的创建也许就要用到其他的设计模式了

抱歉!评论已关闭.