zoukankan      html  css  js  c++  java
  • 抽象工厂模式

     

    一、 抽象工厂(Abstract Factory)模式

    抽象工厂模式是全部形态的工厂模式中最为抽象和最具一般性的一种形态。

    为了方便引进抽象工厂模式,引进一个新概念:产品族(Product Family)。所谓产品族,是指位于不同产品等级结构,功能相关联的产品组成的家族。如图:

     

    图中一共同拥有四个产品族,分布于三个不同的产品等级结构中。仅仅要指明一个产品所处的产品族以及它所属的等级结构,就能够唯一的确定这个产品。

    引进抽象工厂模式

    所谓的抽象工厂是指一个工厂等级结构能够创建出分属于不同产品等级结构的一个产品族中的全部对象。假设用图来描写叙述的话,例如以下图:

     

    二、 Abstract Factory模式的结构:

     

    图中描写叙述的东西用产品族描写叙述例如以下:

     


    抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。

    详细工厂(Concrete Factory)角色:这个角色直接在client的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。

    抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共有的接口。

    详细产品(Concrete Product)角色:抽象工厂模式所创建的不论什么产品对象都是某一个详细产品类的实例。这是client终于须要的东西,其内部一定充满了应用系统的商业逻辑。


    三、 程序举例:

    该程序演示了抽象工厂的结构,本身不具有不论什么实际价值。

    // Abstract Factory pattern -- Structural example  
    using System;

    // "AbstractFactory"
    abstract class AbstractFactory
    {
      
    // Methods
      abstract public AbstractProductA CreateProductA();
      
    abstract public AbstractProductB CreateProductB();
    }


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

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

    }


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


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

    }


    // "AbstractProductA"
    abstract class AbstractProductA
    {
    }


    // "AbstractProductB"
    abstract class AbstractProductB
    {
      
    // Methods
      abstract public void Interact( AbstractProductA a );
    }


    // "ProductA1"
    class ProductA1 : AbstractProductA
    {
    }


    // "ProductB1"
    class ProductB1 : AbstractProductB
    {
      
    // Methods
      override public void Interact( AbstractProductA a )
      
    {
        Console.WriteLine( 
    this + " interacts with " + a );
      }

    }


    // "ProductA2"
    class ProductA2 : AbstractProductA
    {
    }


    // "ProductB2"
    class ProductB2 : AbstractProductB
    {
      
    // Methods
      override public void Interact( AbstractProductA a )
      
    {
        Console.WriteLine( 
    this + " interacts with " + a );
      }

    }


    // "Client" - the interaction environment of the products
    class Environment
    {
      
    // Fields
      private AbstractProductA AbstractProductA;
      
    private AbstractProductB AbstractProductB;

      
    // Constructors
      public Environment( AbstractFactory factory )
      
    {
        AbstractProductB 
    = factory.CreateProductB();
        AbstractProductA 
    = factory.CreateProductA();
      }

     
      
    // Methods
      public void Run()
      
    {
        AbstractProductB.Interact( AbstractProductA );
      }

    }


    /// <summary>
    /// ClientApp test environment
    /// </summary>

    class ClientApp
    {
      
    public static void Main(string[] args)
      
    {
        AbstractFactory factory1 
    = new ConcreteFactory1();
        Environment e1 
    = new Environment( factory1 );
        e1.Run();

        AbstractFactory factory2 
    = new ConcreteFactory2();
        Environment e2 
    = new Environment( factory2 );
        e2.Run();
      }

    }


    四、 在什么情形下使用抽象工厂模式:

    在下面情况下应当考虑使用抽象工厂模式:

    • 一个系统不应当依赖于产品类实例怎样被创建、组合和表达的细节,这对于全部形态的工厂模式都是重要的。
    • 这个系统有多于一个的产品族,而系统仅仅消费当中某一产品族。
    • 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
    • 系统提供一个产品类的库,全部的产品以相同的接口出现,从而使client不依赖于实现。

    五、 抽象工厂的起源

    据说最早的应用是用来创建在不同操作系统的视窗环境下都可以执行的系统。比方在Windows与Unix系统下都有视窗环境的构件,在每个操作系统中,都有一个视窗构件组成的构件家族。我们可以通过一个抽象角色给出功能描写叙述,而由详细子类给出不同操作系统下的详细实现,如图:

     

    能够发现上面产品类图有两个产品等级结构,各自是Button与Text;同一时候有两个产品族:Unix产品族与Windows产品族。

     

    系统对产品对象的创建要求由一个工厂的等级结构满足。当中有两个详细工厂角色,即UnixFactory和WinFactory。UnixFactory对象负责创建Unix产品族中的产品,而WinFactory负责创建Windows产品族中的产品。

     

    显然一个系统仅仅可以在某一个操作系统的视窗环境下执行,而不能同一时候在不同的操作系统上执行。所以,系统实际上仅仅能消费属于同一个产品族的产品。

    在现代的应用中,抽象工厂模式的使用范围已经大大扩大了,不再要求系统仅仅能消费某一个产品族了。


    六、 Abstract Factory模式在实际系统中的实现

    Herbivore:草食动物
    Carnivore:食肉动物
    Bison:['baisn],美洲或欧洲的野牛

    以下实际代码演示了一个电脑游戏中创建不同动物的抽象工厂。虽然在不同大陆下动物物种是不一样的,但动物间的关系仍然保留了下来。

    // Abstract Factory pattern -- Real World example  
    using System;

    // "AbstractFactory"
    abstract class ContinentFactory
    {
      
    // Methods
      abstract public Herbivore CreateHerbivore();
      
    abstract public Carnivore CreateCarnivore();
    }


    // "ConcreteFactory1"
    class AfricaFactory : ContinentFactory
    {
      
    // Methods
      override public Herbivore CreateHerbivore()
      
    return new Wildebeest(); }

      
    override public Carnivore CreateCarnivore()
      
    return new Lion(); }
    }


    // "ConcreteFactory2"
    class AmericaFactory : ContinentFactory
    {
      
    // Methods
      override public Herbivore CreateHerbivore()
      
    return new Bison(); }

      
    override public Carnivore CreateCarnivore()
      
    return new Wolf(); }
    }


    // "AbstractProductA"
    abstract class Herbivore
    {
    }


    // "AbstractProductB"
    abstract class Carnivore
    {
      
    // Methods
      abstract public void Eat( Herbivore h );
    }


    // "ProductA1"
    class Wildebeest : Herbivore
    {
    }


    // "ProductB1"
    class Lion : Carnivore
    {
      
    // Methods
      override public void Eat( Herbivore h )
      
    {
        
    // eat wildebeest
        Console.WriteLine( this + " eats " + h );
      }

    }


    // "ProductA2"
    class Bison : Herbivore
    {
    }


    // "ProductB2"
    class Wolf : Carnivore
    {
      
    // Methods
      override public void Eat( Herbivore h )
      
    {
        
    // Eat bison
        Console.WriteLine( this + " eats " + h );
      }

    }


    // "Client"
    class AnimalWorld
    {
      
    // Fields
      private Herbivore herbivore;
      
    private Carnivore carnivore;

      
    // Constructors
      public AnimalWorld( ContinentFactory factory )
      
    {
        carnivore 
    = factory.CreateCarnivore();
        herbivore 
    = factory.CreateHerbivore();
      }


      
    // Methods
      public void RunFoodChain()
      
    { carnivore.Eat(herbivore); }
    }


    /// <summary>
    ///  GameApp test class
    /// </summary>

    class GameApp
    {
      
    public static void Main( string[] args )
      
    {
        
    // Create and run the Africa animal world
        ContinentFactory africa = new AfricaFactory();
        AnimalWorld world 
    = new AnimalWorld( africa );
        world.RunFoodChain();

        
    // Create and run the America animal world
        ContinentFactory america = new AmericaFactory();
        world 
    = new AnimalWorld( america );
        world.RunFoodChain();
      }

    }

    抽象工厂的另外一个样例:

    怎样设计抽象类工厂留作思考。


    七、 "开放-封闭"原则

    "开放-封闭"原则要求系统对扩展开放,对改动封闭。通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包含双方面:

    添加产品族:Abstract Factory非常好的支持了"开放-封闭"原则。

    添加新产品的等级结构:须要改动全部的工厂角色,没有非常好支持"开放-封闭"原则。

    综合起来,抽象工厂模式以一种倾斜的方式支持添加新的产品,它为新产品族的添加提供方便,而不能为新的产品等级结构的添加提供这种方便。


    參考文献:
    阎宏,《Java与模式》,电子工业出版社
    [美]James W. Cooper,《C#设计模式》,电子工业出版社
    [美]Alan Shalloway  James R. Trott,《Design Patterns Explained》,中国电力出版社
    [美]Robert C. Martin,《敏捷软件开发-原则、模式与实践》,清华大学出版社
    [美]Don Box, Chris Sells,《.NET本质论 第1卷:公共语言执行库》,中国电力出版社

  • 相关阅读:
    Windows server 2016 解决“无法完成域加入,原因是试图加入的域的SID与本计算机的SID相同。”
    Windows Server 2016 辅助域控制器搭建
    Windows Server 2016 主域控制器搭建
    Net Framework 4.7.2 覆盖 Net Framework 4.5 解决办法
    SQL SERVER 2012更改默认的端口号为1772
    Windows下彻底卸载删除SQL Serever2012
    在Windows Server2016中安装SQL Server2016
    SQL Server 创建索引
    C#控制台或应用程序中两个多个Main()方法的设置
    Icon cache rebuilding with Delphi(Delphi 清除Windows 图标缓存源代码)
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4303028.html
Copyright © 2011-2022 走看看