design pattern factory method #Reprinted#

引入人、工厂、和斧子的问题:
  (1),原始社会时,劳动社会基本没有分工,需要斧子的人(调用者)只好自己去磨一把斧子,每个人拥有自己的斧子,如果把大家的石斧改为铁斧,需要每个人都要学会磨铁斧的本领,工作效率极低。
对应Java里的情形是:java程序里的调用者new一个被调用者的实例。类耦合度极高,修改维护烦琐,效率极低。
  (2),工业社会时,工厂出现,斧子不再由普通人完成,而由工厂生产,当人们需要斧子的时候,可以到工厂购买斧子,无需关心斧子是怎么制造出来的,如果废弃铁斧为钢斧,只需改变工厂的制造工艺即可,制作工艺是工厂决定的,工厂生产什么斧子,工人们就得用什么斧子。
      对应的Java里的情形是:Java程序的调用者可以以来简单工厂创建被调用者,变化点被隔离到了简单工厂里,虽然耦合度降低,但是调用者会和工厂耦合,而且需要定位自己的工厂。
(3)近代工业社会,工厂蓬勃发展,人们需要什么斧子,只需要提供一个斧子图形,商家会按照你提供的图形将你的斧子订做好,送上门。

工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A(). 工厂模式也是用来创建实例对象的,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

工厂方式封装:

Sample有个继承如MySample

public class Factory{  
  public static Sample creator(int which){  
     //getClass 产生Sample 一般可使用动态类装载装入类。  
if (which==1)  
    return new SampleA();

  else if (which==2)

return new SampleB(); 
  }

在程序中,如果要实例化Sample时.就使用

Sample sampleA=Factory.creator(1);

在列举个例子:

比如你写了个应用,里面用到了数据库的封装,你的应用可以今后需要在不同的数据库环境下运行,可能是oracle,db2,sql server等,那么连接数据库的代码是不一样的,你用传统的方法,就不得不进行代码修改来适应不同的环境,非常麻烦,但是如果你采用工厂类的话,将各种可能的数据库连接全部实现在工厂类里面,通过你配置文件的修改来达到连接的是不同的数据库,那么你今后做迁移的时候代码就不用进行修改了。

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

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

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

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

引进抽象工厂模式

所谓的抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。如果用图来描述的话,如下图:

二、 Abstract Factory模式的结构:

图中描述的东西用产品族描述如下:

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

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

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

具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。

三、 程序举例:

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

// 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();
  }
}

  

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

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

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

五、 抽象工厂的起源

据说最早的应用是用来创建在不同操作系统的视窗环境下都能够运行的系统。比如在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很好的支持了"开放-封闭"原则。

增加新产品的等级结构:需要修改所有的工厂角色,没有很好支持"开放-封闭"原则。

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

时间: 2024-10-09 08:10:40

design pattern factory method #Reprinted#的相关文章

Design Pattern ——Factory Method&amp;Abstract Factory

今天开始复习设计模式.设计模式相关的资料有很多,概念性的东西就画个图就可以了.把关注点放在例子上,设计模式还是要使用中才有感受. 从Factory Method&Abstract Factory开始. 一.Factory Method 工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中. 我们的例子如下: 我们项目中有一个代码提交记录releasenote,我们需要将这个releasenote分成csv/xls/xml格式分别导出 1 public interface

[Design Pattern] Factory Pattern 简单案例

Factory Pattern , 即工厂模式,用于创建对象的场景,属于创建类的设计模式 . 下面是一个工厂模式案例. Shape 作为接口, Circle, Square, Rectangle 作为具体类实现了 Shape 接口. ShapeFactory 封装了创建各个 Shape 的方式,隐藏了 new 命令.FactoryPatternDemo 用于演示工厂模式. 具体代码: Shape 接口定义 public interface Shape { public void draw();

Design Pattern - Template Method(C )

Definition Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. Participants The classes and/or obj

Design Pattern :Factory and Reflect in java

interface page {     void Render(); } class pageA implements page {     @Override     public void Render() {          System.out.println("I am " + this.getClass().getName());     } } class pageB implements page {     @Override     public void Re

[design pattern](5) Factory Method

前言 在前面一章博主介绍了简单工厂模式(Simple Factory),接着上面的章节,今天博主就来介绍下工厂方法模式(Factory Method). 思考题 首先,让我们来思考下面的问题: 在上一章的内容中我们提到了,博主开了一家饭店,那么,因为经营有方,博主准备在四川和上海开饭店了,也还是那两个菜,大家都知道上海和四川的口味差距非常的大,上海口味偏甜,那么四川口味偏辣.所以为了迎合当地人的口味,我们需要做不同口味的菜.那么你们会怎么做呢? 这时我们如果在原有的简单工厂上添加不同口味的菜,就

工厂方法模式(Factory Method Pattern)

2. 工厂方法模式(Factory Method Pattern) 2.1. 模式动机 现在对该系统进行修改,不再设计一个按钮工厂类来统一负责所有产品的创建,而是将具体按钮的创建过程交给专门的工厂子类去完成,我们先定义一个抽象的按钮工厂类,再定义具体的工厂类来生成圆形按钮.矩形按钮.菱形按钮等,它们实现在抽象按钮工厂类中定义的方法.这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的按钮类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新按钮的实例,这一

简单工厂设计模式(Simple Factory Design Pattern)

[引言]最近在Youtub上面看到一个讲解.net设计模式的视频,其中作者的一个理解让我印象很深刻:所谓的设计模式其实就是运用面向对象编程的思想来解决平时代码中的紧耦合,低扩展的问题.另外一点比较有见解的是,区分了设计模式(Design Pattern),结构模式(Architecture Pattern),架构类型(Architecture Style). 如下图所示 Design Pattern:是基于代码层面的,就是针对解决功能模块之间的问题而采用恰当的设计模式,比如依赖注入,简单工厂,适

Abstract Factory Design Pattern 抽象工厂设计模式 - 总结

Abstract Factory Design Pattern 就是一般的Factory Design Pattern的进一步设计,增加一个抽象工厂,然后利用这个工厂可以创建不同基类的类. 当我们需要创建更多不同类的时候就可以使用这个设计模式了. 这个设计模式的代码相对会多点,但是其中的思想就是一般Factory Design Pattern,然后集合更多的基类,看起来挺大的一个设计模式,其思想是挺简单的. 其中具体的实现细节当然是可以有多种实现方法的: 1 利用Factory的基类衍生出不同的

Software Engineering | Factory method pattern

工厂对象通常包含一个或多个方法,用来创建这个工厂所能创建的各种类型的对象.这些方法可能接收参数,用来指定对象创建的方式,最后返回创建的对象. 有时,特定类型对象的控制过程比简单地创建一个对象更复杂.在这种情况下,工厂对象就派上用场了.工厂对象可能会动态地创建产品对象的类,或者从对象池中返回一个对象,或者对所创建的对象进行复杂的配置,或者应用其他的操作. 这些类型的对象很有用.几个不同的设计模式都应用了工厂的概念,并可以使用在很多语言中.例如,在<设计模式>一书中,像工厂方法模式.抽象工厂模式.