Design Pattern - Creational - Factory 模式系列

简单介绍:

  工厂模式专门负责将大量有共同接口的类实例化。
  工厂模式可以动态决定实例化哪一个类。不必事先知道每次要实例化哪个类。

工厂模式的几种形态:

  简单工厂(Simple Factory)
    又称静态工厂模式
    <由一个具体工厂类使用静态方法根据客户端传入的数据决定创建那种产品>
    [main]
      Product prod = Creator.factory(type1);

  工厂方法(Factory Method)
    又称多态性工厂模式或虚拟构造子模式(Virtual Constructor)
    <客户端首先决定创建哪种具体的工厂类,然后由工厂类创建具体的产品类>
    [main]
      Creator creator1 = new ConcreteCreator1();
      Product prod1 = creator1.factory();

  抽象工厂(Abstract Factory)
    又称工具模式(Kit or Toolkit)
    <引入产品族的概念,形成二维的产品等级结构>
    <客户端首先确定使用哪个族的产品,然后创建对应族的具体工程方法,再由工厂方法创建具体的产品类>
    [main]
      Creator creator1 = new ConcreteCreator1();
      Product prod1 = creator1SerialA();

一、简单工厂模式

  由一个工厂对象决定创建出哪一种产品类的实例。
  它是普通工厂模式的一个特例

  涉及到的角色:
    工厂类(FruitGenerator)
    抽象产品(Fruit)
    具体产品(Apple,Strawberry,Grape)

  经典例子:
     DateFormat的getDateInstance()方法

二、普通工厂模式

  用意:定义一个创建产品对象的工厂接口,将实际的创建工作推迟到子类中。

  它扩展了子类实例化的思想,不再由单个工厂类决定到底应该实例化哪个子类,而超类则会将这一决

定推迟到每个子类中完成。
  好处:可以使系统在不修改具体工厂角色的情况下引进新的产品。这很好的符合了“开放-封闭”原则。 

  涉及到的角色:
    抽象工厂
    具体工厂
    抽象产品
    具体产品

  具体设计方法:
    在一个系统设计中,常常是首先有产品角色,然后又工厂角色。
    在可以应用工厂方法模式的情形下,一般都会有一个产品的等级结构。
    由一个(甚至多个)抽象产品和多个具体产品组成。
    应用工厂方法模式时,常用的一个做法是按照产品的等级结构设计一个同结构的工厂等级结构。

  工厂方法VS简单工厂
    工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
    工厂方法模式运行很多具体工厂类从抽象工厂类中将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。

三、抽象工厂

  起源:用于创建分属于不同操作系统的视窗构建。

  抽象工厂VS工厂方法
    工厂方法针对的是一个产品等级结构;
    抽象工厂需要面对多个产品等级结构

  涉及到的角色:
    抽象工厂
    具体工厂
    抽象产品
    具体产品

  考虑使用抽象工厂模式的情形:
    “生产”系统有多于一个的产品族,而“客户”系统只消费其中某一产品族
    属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来

四、使用工厂模式的目的

  符合设计模式的原则针对接口的编程。
  如果使用new方法创建对象,就会造成客户程序紧密依赖具体的产品类。
  而如果使用工厂方法创建,可以起到隔离具体产品类的效果。
  符合开闭原则,符合依赖倒置原则(DIP)

五、工厂模式简单的例子

  1. 简单工厂

public interface Product{
}

public class ConcreteProduct1 implements Product{
public ConcreteProduct1(){}
}

public class Creator{
public static Product factory(int type){
    if(type==1)
return new ConcreteProduct1();
else if(type==2)
return new ConcreteProduct2();
else
...
}
}

public class Client{
public static void main(String[] args){
Product prod = Creator.factory(1);
}
}

  2. 工厂方法

public interface Product{}

public class ConcreteProduct1 implements Product{
public ConcreteProduct1(){
//do something
}
}

public interface Creator{
public Product factory();
}

public class ConcreteCreator1 implements Creator{
public Product factory(){
return new ConcreteProduct1();
}
}

public class Client{
public static void main(String[] args){
Creator creator1 = new ConcreteCreator1();
Product prod1 = creator1.factory();
}
}

  3. 抽象工厂


public interface ProuductA{}

public class ProductA1 implements ProductA{
public ProductA1(){}
}
public class ProductA2 implements ProductA{
public ProductA2(){}
}

public interface ProuductB{}
public class ProductB1 implements ProductA{
public ProductB1(){}
}
public class ProductB2 implements ProductA{
public ProductB2(){}
}

public interface Creator{
//产品系列A的工厂方法
public ProductA factoryA();
//产品系列B的工程方法
public ProductB factoryB();
}

public class ConcreteCreator1 implements Creator{
public ProductA factoryA(){
return new ProductA1();
}
public ProductB factoryB(){
return new ProductB1();
}
}
public class ConcreteCreator2 implements Creator{
...
}

public class Client{
public static void main(String[] args){
Creator creator1 = new ConcreteCreator1();
Product prod1 = creator1.factoryA();
}
}

六、工厂方法在《java与模式》中的例子(果园)

  1. 简单工厂

public interface Fruit{
void plant();
void grow();
void harvest();
}

public class Apple implements Fruit{
public void plant(){
System.out.println("Apple has been planted");
}

public void grow(){
System.out.println("Apple is growing...");
}

public void harvest(){
System.out.println("Apple has been harvested.");
}
}

public class Strawberry implements Fruit{
...
}

public class Grape implements Fruit{
...
}

public class FruitGardener{
public static Fruit factory(String which) throws BadFruitException{
if(which.equals("apple"))
return new Apple();
else if(which.equals("strawberry"))
return new Strawberry();
else if(which.equals("grape"))
return new Grape();
else
throw new BadFruitException("Bad fruit request.");
}
}

public class Client{
public static void main(String[] args) throws Exception{
Fruit f1 = FruitGardener.factory("grape");
f1.plant();
f1.grow();
f1.harvest();

Fruit f2 = FruitGardener.factory("strawberry");
...
}
}

  2. 工厂方法

public interface Fruit{
void plant();
void grow();
void harvest();
}

public class Apple implements Fruit{
public void plant(){
System.out.println("Apple has been planted");
}

public void grow(){
System.out.println("Apple is growing...");
}

public void harvest(){
System.out.println("Apple has been harvested.");
}
}

public interface FruitGardener{
public Fruit factory();
}

public class AppleGardener implements FruitGardener{
public Fruit factory(){
return new Apple();
}
}

public class Client{
public static void main(String[] args) throws Exception{
FruitGardener appleGardener = new AppleGardener();
Fruit apple = appleGardener.factory();
}
}

  3. 抽象工厂

public interface Veggie{}
public class NorthernVeggie implements Veggie{
private String name;
public NorthernVeggie(String name){
this.name = name;
}
}
public class TropicalVeggie implements Veggie{
private String name;
public TropicalVeggie(String name){
this.name = name;
}
}

public interface Fruit{}
public class NorthernFruit implements Fruit{
private String name;
public NorthernFruit(String name){
this.name = name;
}
}
public class TropicalFruit implements Fruit{
private String name;
public TropicalFruit(String name){
this.name = name;
}
}

public interface Gardener{
public Fruit createFruit(String name);
public Veggie createVeggie(String name);
}

public class NorthernGardener implements Gardener{
public Fruit createFruit(String name){
return new NorthernFruit(name);
}

public Veggie createVeggie(String name){
return new NorthernVeggie(name);
}
}

public class TropicalGardener implements Gardener{
public Fruit createFruit(String name){
return new TropicalFruit(name);
}

public Veggie createVeggie(String name){
return new TropicalVeggie(name);
}
}

七、在Java中的应用

  1. 简单工厂:

    DateFormat的getDateInstance()方法是一个静态方法。
    【旁白起】
    如果它是一个非静态的普通方法会怎样呢?
    要使用这个(非静态)方法,客户端必须首先取得这个类的实例或者其子类的实例。
    而这个类是一个抽象类,不可能有自己的实例,所以客户端就只好首先取得其具体子类的实例。
    如果客户端能够取得它的子类的实例,那么还需要这个工厂方法干什么?
    【旁白止】 

    显然,这里使用静态工厂方法是为了将具体子类实例化的工作隐藏起来,从而客户端不必考虑如何
    将具体子类实例化,因为抽象类DateFormat会提供它的合适的具体的实例。
    这是一个简单工厂方法模式的绝佳应用。

    与一般的简单工厂模式不同的地方在于,这里的工厂角色与抽象产品角色合并成一个类。
    换言之,抽象产品角色负责具体产品角色的创建,这是简单工厂模式的一个特例。

   2. 工厂方法:

#### EJB中的工厂模式:####
Context ctx = new InitialContext();
EmployeeHome home = (EmployeeHome)ctx.lookup("Employee");

//标准工厂方法模式
Employee emp = home.create(1001, "John", "Smith");
emp.setTelephone("13822334455");

#### JMS中的工厂方法模式:####
Properties prop = new Properties();
prop.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");
prop.put(Context.PROVIDER_URL, "file:C:\temp");
Context ctx = new InitialContext(prop);
//利用ctx索取工厂类实例
Topic topic = (Topic)ctx.lookup("myTopic");
TopicConnectionFactory tcf = (TopicConnectionFactory)ctx.lookup("myTCF");
//利用工厂类创建Connection,这是典型的工厂模式
TopicConnection tConn = tcf.createTopicConnection();
//利用Connection创建Session实例,也是工厂模式
TopicSession tSess = tCon.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
//利用Session创建Producer的实例,还是工厂模式
TopicPublisher publisher = tSess.createPublisher(topic);
//利用Session创建消息实例,又是工厂模式
TextMessage msg = tSess.createTextMessage("Hello from Jeff");
publisher.publish(msg);

  3. 抽象工厂:
     用于创建分属于不同操作系统的视窗构建

八、参考文档
  《Java与模式》工厂系列模式部分 
  http://wenku.baidu.com/view/6c454893daef5ef7ba0d3cb3.html 

posted @ 2012-02-01 22:09  万法自然~  阅读(249)  评论(0编辑  收藏  举报