初识常用12种设计模式---(其二)抽象工厂(abstract factory)

1.抽象工厂设计模式

  • 1.1 什么是抽象工厂?
    • 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
    • 抽象工厂模式属于创建模式之一,创建模式主要是对类的实例化进行了抽象
  • 1.2 解决问题的思路是什么?
    • 1.2.1: 一个是只知道所需要的一系列对象的接口,而不知具体实现,或者是不知道具体使用哪一个实现
    • 1.2.2: 另一个是这一系列对象是相关或者相互依赖的,也就是说纪要创建接口的对象,还要约束它们之间的关系
    • 1.2.3: 工厂方法或简单工厂就是解决只知道接口不知道实现的问题,为什么不用它们呢?
      解:因为它们关注的是单个产品对象的创建,而不是一系列产品

2.抽象工厂问题

  • 2.1: 问题:现在客户要求工程师组装一台计算机,其中相应的CPU和主板等配件由客户自己自由选择,那么客户如何选取对应匹配的CPU和主板呢?
  • 2.2: 提示:CPU有多种,主板也有多种。CPU中的针脚数要对应主板中的插槽数、CPU的频率(主频)要与主板中的总线频率对应等等条件。(在此我们只以针脚和插槽为例)
  • 2.3: 示例:CPU提供IntelCPU、HPCPU、AMDCPU;主板提供Intel_ATXMB、HS_ATXMB、JJ_ATXMB。
  • 2.4: 注意:IntelCPU是不能与JJ_ATXMB和Intel_ATXMB匹配的

以下数据均是示例,不匹配真实数据

配件类型 针脚\插槽数
IntelCPU 1000
AMDCPU 2000
HPCPU(惠普CPU) 3000
HS_ATXMB(华硕主板) 1000
JJ_ATXMB(技嘉主板) 2000
Intel_ATXMB 3000

3.不同模式的解决方案

  • 对于工程师装机,只是知道CPU和主板的接口,而不知道具体实现,那么用工厂方法或者简单工厂即可实现。但是因为两个工厂模式都是对单个产品进行创建,无法做到产品间的相互关联,所以会出现IntelCPU(1000)和Intel_ATXMB(3000)不匹配的情况。(具体代码暂且不提供)

4.抽象工厂

  • 4.1: 结构:
    在这里插入图片描述
  • 4.2: 说明:
    • 4.2.1: AbstractFactory:抽象工厂,定义创建一系列产品对象的接口
    • 4.2.2: ConcreteFactory:具体工厂,实现抽象工厂定义的方法,具体实现一系列产品对象的创建
    • 4.2.3: AbstractProduct:定义一类有关联产品对象的接口
    • 4.2.4: ConcreteProduct:具体的产品实现对象,通常在具体工厂里面,会选择具体的产品实现对象,来创建符合抽象工厂定义的方法返回的产品类型的对象
    • 4.2.5: Client:客户端,主要使用抽象工厂来获取一系列所需要的产品对象,然后面向这些产品对象的接口编程,以实现需要的功能
  • 4.3: 伪代码:
    /// <summary>
    /// 声明一系列产品的操作接口
    /// </summary>
    public interface abstractfactory
    {
        /// 创建CPU的方法对象
        CPUAPI cpu();
        /// 创建主板的方法对象
        MainBorderAPI mainBorder();
    }

    #region==系列产品接口==
    /// <summary>
    /// 声明一个产品接口:CPU
    /// </summary>
    public interface CPUAPI
    {
        //CPU的针脚数
        int CPUPins { get; set; }
        //输出CPU的针脚数
        void PrintCPUPins();
    }
    /// <summary>
    /// 声明一个产品接口:主板
    /// </summary>
    public interface MainBorderAPI
    {
        //主板的针脚插槽数
        int MBHoles { get; set; }
        //输出主板的插槽数
        void PrintMBHoles();
    }
    #endregion
    
    #region==CPU产品类==
    /// <summary>
    /// 实现CPU接口的具体产品类:Intel
    /// </summary>
    public class IntelCPU : CPUAPI
    {
        //因特尔的CPU针脚数1000
        private int cpuPins = 1000;
        //给接口的属性赋值
        public int CPUPins
        {
            get { return cpuPins; }
            set { cpuPins = value; }
        }
        public IntelCPU()
        {

        }
        public void PrintCPUPins()
        {
            Console.WriteLine("IntelCPU Pins:" + this.CPUPins);
        }
    }......(还有两个在此不列出)
        #endregion

    #region==主板产品类==    
    /// <summary>
    /// 实现主板接口的具体产品类:华硕ATX
    /// </summary>
    public class HS_ATXMB : MainBorderAPI
    {
        //华硕的插槽数1000
        private int mbHoles = 1000;
        //给接口的属性赋值
        public int MBHoles
        {
            get { return mbHoles; }
            set { mbHoles = value; }
        }
        public void PrintMBHoles()
        {
            Console.WriteLine("MBHoles:" + this.MBHoles);
        }
    }......(还有两个在此不列出)
    #endregion
    
    #region==实现抽象工厂==
    /// <summary>
    /// 抽象工厂实现1:IntelCPU+华硕MB
    /// </summary>
    public class ImplementFactory1:abstractfactory
    {
        public CPUAPI cpu()
        {
            return new IntelCPU();
        }
        public MainBorderAPI mainBorder()
        {
            return new HS_ATXMB();
        }
    }......(还有两个在此不列出)
    #endregion

    main()
    {
         //这个new ImplementFactory1();是用这个类的对象的 构造函数 来实例化抽象工厂接口对象
         abstractfactory af = new ImplementFactory1();
         //此处如果写成af.cpu()就出问题。因为该af接口对象是由构造函数实例化,
         //那么它只会去调用实现该接口的类IntelCPU的构造函数,然后运行完构造函数则退出。
         //所以必须是af.cpu().PrintCPUPins();
         af.cpu().PrintCPUPins();
         af.mainBorder().PrintMBHoles();
    }


5.抽象工厂的优缺点

  • 优点:
    • 5.1: 分离接口与实现 :客户端使用抽象工厂来创建需要的对象,而客户端根本不知道具体的实现是谁,客户端只是面向产品的接口编程。也就是,客户端从具体的产品实现中解耦
    • 5.2: 使得切换产品簇变得容易 : 因为一个具体的工厂实现代表的是一个产品簇,如上面的ImplementFactory1就是一个工厂,然后ImplementFactory2就是另一个。客户端选用不同的工厂实现,就相当于在切换不同的产品簇。
  • 缺点:
    • 5.1: 不太容易扩展新的产品 :比如要给产品簇增加一个新的产品,那么abstractfactory也要变,concertefactory也要变,abstractproduct也要变,concreteproduct仍然要变,所以不容易扩展。
    • 5.2: 容易造成类层次复杂

6.参考文献

  • 研磨设计

猜你喜欢

转载自blog.csdn.net/qq_40258437/article/details/88076318