工厂模式

1.1 简单工厂(Simple Factory)模式


简单工厂模式是类的创建,又叫静态工厂方法(Static Factory Methord)模式。简单工厂模式是由一个工厂对象决定创造哪一种产品类的实例。
 
1.1.1 工厂模式的几种形态

工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态的决定将哪一个类实例化,工厂模式有以下几种形态:
 简单工厂(Simple Factory)模式:又称静态工厂方法(Static Factory Methord)模式。
 工厂方法(Factory Method)模式:又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式。
 抽象工厂(Abstract Factory)模式:又称工具箱(Kit或Toolkit)模式。
下图所示的就是简单工厂模式的简略类图。
点击在新窗口查看全图

简单工厂模式,或称静态工厂方法模式,是不同工厂方法模式的一个特殊实现。在Java语言中,通常的工厂方法模式不能通过设计功能的退化给出静态工厂方法模式。
 
1.1.2 简单工厂模式的引进(一般模式)
比如有一个农场,生产各种水果,有苹果(Apple)、草莓(Strawberry)、葡萄(Grape);农场的园丁(FruitGardener)要根据客户的需求,提供相应的水果。下面看看是如何用简单工厂模式实现这个过程的,如下图:
点击在新窗口查看全图

 
此模式的实现源码如下:
 
1.1.2.1 产品接口-水果接口:Fruit.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式模式--简单工厂模式--一般模式
 * ReadMe:  抽象产品角色:工厂的水果产品接口--水果
 */
public interface Fruit {
    /**
     * 种植
     */
    void plant();
    /**
     * 生长
     */
    void grow();
    /**
     * 收获
     */
    void harvest();
}
 
1.1.2.2 产品-平果类:Apple.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式模式--简单工厂模式--一般模式
 * ReadMe:  水果工厂的产品:苹果
 */
public class Apple implements Fruit {
    private int treeAge;
    /**
     * 种植
     */
    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.");
    }
    /**
     * @return 返回树龄
     */
    public int getTreeAge() {
        return treeAge;
    }
    /**
     * 设置树龄
     */
    public void setTreeAge(int treeAge) {
        this.treeAge = treeAge;
    }
}
 
1.1.2.3 产品-草莓类:Strawberry.java
/**
 * * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式模式--简单工厂模式--一般模式
 * ReadMe:  水果工厂的产品:草莓
 */
public class Strawberry implements Fruit {
    /**
     * 生长
     */
    public void grow() {
        System.out.println("Strawberry is growing...");
    }
    /**
     * 收获
     */
    public void harvest() {
        System.out.println("Strawberry has been harvested.");
    }
    /**
     * 种植
     */
    public void plant() {
        System.out.println("Strawberry has been planted.");
    }
    /**
     * 辅助方法
     */
    public static void log(String msg) {
        System.out.println(msg);
    }
}
 
1.1.2.4 产品-葡萄类:Grape.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式模式--简单工厂模式--一般模式
 * ReadMe:  水果工厂的产品:葡萄
 */
public class Grape implements Fruit {
    private boolean seedless;   //是否有籽
    /**
     * 种植
     */
    public void plant() {
        System.out.println("Grape has been planted.");
    }
    /**
     * 生长
     */
    public void grow() {
        System.out.println("Grape is growing...");
    }
    /**
     * 收获
     */
    public void harvest() {
        System.out.println("Grape has been harvested.");
    }
    /**
     * @return 是否有籽
     */
    public boolean getSeedless() {
        return seedless;
    }
    /**
     * 有无籽的赋值方法
     */
    public void setSeedless(boolean seedless) {
        this.seedless = seedless;
    }
    /**
     * 辅助方法
     */
    public static void log(String msg) {
        System.out.println(msg);
    }
}
 
1.1.2.5 工厂-园丁类:FruitGardener.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式模式--简单工厂模式--一般模式
 * ReadMe:  工厂类角色: 水果园丁,生产水果产品
 */
public class FruitGardener {
    /**
     * 静态工厂方法
     * @param which :具体的产品名称
     * @return 一个水果对象
     * @throws BadFruitException
     */
    public static Fruit factory(String which) throws BadFruitException {
        if (which.equalsIgnoreCase("apple")) {
            return new Apple();
        } else if (which.equalsIgnoreCase("strawberry")) {
            return new Strawberry();
        } else if (which.equalsIgnoreCase("grape")) {
            return new Grape();
        } else {
            throw new BadFruitException("Bad fruit request");
        }
    }
}
 
1.1.2.6 工厂异常定义类:BadFruitException.java
/**
 *  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式模式--简单工厂模式--一般模式
 * ReadMe:  工厂的异常处理类
 */
public class BadFruitException extends Exception {
    public BadFruitException(String msg) {
        super(msg);     //调用父类的构造方法
    }
}
 
1.1.2.7 一般工厂模式的测试类
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式模式--简单工厂模式--一般模式
 * ReadMe:  一般工厂模式的测试类
 */
public class TestApp {
    /**
     * 测试方法
     */
    private void test(String fruitName) {
        try {
            Fruit f = FruitGardener.factory(fruitName);
            System.out.println("恭喜!生产了一个水果对象:" + fruitName);
        } catch (BadFruitException e) {
            System.out.println("对不起!工厂目前不能生产你所要的产品:" + fruitName);
            System.out.println(e.getMessage());     //输出异常信息
            e.printStackTrace();                    //输出异常堆栈信息
        }
    }
    /**
     * 应用入口方法
     */
    public static void main(String args[]) {
        TestApp t = new TestApp();
        t.test("apple");
        t.test("grape");
        t.test("strawberry");
        t.test("car");  //此处会抛异常,水果工厂能生产car(轿车)吗!哈哈哈哈...
    }
}
 
1.1.2.8 测试运行结果
恭喜!生产了一个水果对象:apple
恭喜!生产了一个水果对象:grape
恭喜!生产了一个水果对象:strawberry
对不起!工厂目前不能生产你所要的产品:car
Bad fruit request
com.lavasoft.patterns.simplefactory.ybgc.BadFruitException: Bad fruit request
 at com.lavasoft.patterns.simplefactory.ybgc.FruitGardener.factory(FruitGardener.java:28)
 at com.lavasoft.patterns.simplefactory.ybgc.TestApp.test(TestApp.java:19)
 at com.lavasoft.patterns.simplefactory.ybgc.TestApp.main(TestApp.java:37)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:585)
 at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Process finished with exit code 0
从结果看来,有异常,是因为输入了工厂不能生产的类型car(小汽车),哈哈哈哈,果园能生产汽车吗?让幼儿园的小朋友告诉你吧!
 
1.1.3 简单工厂模式的一般性结构

 
总结一下,从上面的简单工厂模式的实现可以看到,简单工厂模式需要实现
 工厂角色:园丁
 抽象产品:水果接口
 具体产品:苹果、葡萄、草莓
另外还一般还需要实现
 工厂异常类
 客户类
简单工厂模式的一般性结构图如下:
点击在新窗口查看全图

1.1.4 简单工厂模式的实现
 
1.1.4.1 使用接口或者抽象类实现多层次的产品结构
工厂类可以有多个静态的工厂方法,分别用来生产不同的产品对象。
 
1.1.4.2 多个工厂方法
分别负责创建不同的产品对象,比如java.text.DateFormat类是其子类的工厂类,而DateFormat类就是提供了多个静态工厂方法。
 
1.1.4.3 抽象产品角色的省略
如果系统仅有一个具体产品角色产品角色的话,那么就可以省略掉抽象产品角色。省略掉抽象产品角色后的简略类图如下:
点击在新窗口查看全图

 
下面是一个例子,工厂角色创建具体产品,源代码如下:
 
1.1.4.3.1 产品角色:ConcreteProduct.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--工抽合并(工厂角色与抽象产品角色合并)
 * ReadMe:  具体产品类,表示单一的一类产品.
 */
public class ConcreteProduct {
    public ConcreteProduct() {
    }
}
 
1.1.4.3.2 工厂角色:
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--工抽合并(工厂角色与抽象产品角色合并)
 * ReadMe:  具体产品类,与抽象产品角色合并,只生产单一种类产品.
 */
public class Creator {
    /**
     * 静态工厂方法
     * @return 一个产品
     */
    public static Creator factory(){
        return new Creator();
    }
}
 
1.1.4.3.3 测试类
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--工抽合并(工厂角色与抽象产品角色合并)
 * ReadMe:  工抽合并测试类
 */
public class TestApp {
    private void test() {
        Creator t = Creator.factory();
        System.out.println("产品成功生产!");
    }
    public static void main(String args[]) {
        new TestApp().test();
    }
}
 
1.1.4.3.4 测试结果
产品成功生产!
Process finished with exit code 0
 
1.1.4.4 工厂角色与抽象角色合并
在有些情况下,工厂角色可以由抽象产品角色扮演。典型的应用就是java.text.DateFormat类,一个抽象产品类同时是子类的工厂,如下图所示:
点击在新窗口查看全图

 
下面是我自己写的一个实现,源代码如下:
 
1.1.4.4.1 抽象产品类(同时又是工厂类)
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--工厂角色与抽象产品角色合并
 * ReadMe:  抽象产品类,同时又是工厂类.
 */
public abstract class AbsProduct {
    static Product factory(){
        return new Product();
    }
}
 
1.1.4.4.2 具体产品类
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--工厂角色与抽象产品角色合并
 * ReadMe:  具体产品类
 */
public class Product {
    Product(){
    }
}
 
1.1.4.4.3 测试类
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--工厂角色与抽象产品角色合并
 * ReadMe:  测试类
 */
public class TestApp {
    private void test() {
        Product a = AbsProduct.factory();
        System.out.println("成功创建一个产品对象!");
    }
    public static void main(String args[]) {
        TestApp test = new TestApp();
        test.test();
    }
}
 
 
1.1.4.4.4 测试结果

成功创建一个产品对象!
Process finished with exit code 0

 
这个实现很简单,代码就不做详细解释了!
 
1.1.4.5 三个角色全部合并

如果在上面例子的基础上,连抽象产品角色都省略了,而工厂角色就可以与具体产品角色合并。换言之,一个产品类为自身的工厂。如下图所示:
点击在新窗口查看全图

 
下面给出一个简单的实现例子如下:
 
1.1.4.5.1 具体产品类
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--三色合一模式
 * ReadMe:  抽象产品,产品,工厂类 三和一后的具体产品类
 */
public class ConcreteProduct
{
 public ConcreteProduct(){}
    /**
     * 静态工厂方法
     * @return 具体的产品ConcreteProduct实例
     */
    public static ConcreteProduct factory()
    {
        return new ConcreteProduct();
    }
}
 
1.1.4.5.2 测试类
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--简单工厂模式--三色合一模式
 * ReadMe:  测试方法
 */
public class TestApp {
    //测试方法
    private void test(){
        ConcreteProduct t=ConcreteProduct.factory();
        System.out.println("产品成功生产!");
    }
    //
    public static void main(String args[]){
        new TestApp().test();
    }
}
 
1.1.4.5.3 测试运行结果
产品成功生产!
Process finished with exit code 0
代码很简单,不解释了。
 
1.1.4.6 产品对象的循环使用和登记式的工厂方法
这里在单例模式和多例模式中在讨论。
简单工厂模式的优点和缺点
 
1.1.4.6.1 简单工厂模式的优点
核心式工厂类,工厂类决定在什么情况下创建哪一种产品类的实例。而客户端则可以免除直接创建产品对象的责任,而仅仅是“消费”产品。简单工厂模式通过这种做法实现了对责任的分割。
 
1.1.4.6.2 简单工厂模式的缺点
当产品类具有复杂的多层次等级结构时,工厂类只有它自己。以不变应万变,是其缺点。
这个工厂类集中了所有产品创建逻辑,形成了一个无所不知的全能类(也称上帝类),如果此类出问题了,整个应用都受大影响。
当产品有多个接口时,判断在什么条件下创建什么产品类实例会很困难。
对于工厂来说,增加新的产品时一个痛苦的过程。工厂角色必须知道每一种产品,如何创建它们,以及何时向客户提供它们。换言之,接纳新的产品意味着修改这个工厂角色的源代码。简单工厂只在有限的程度上支持“开-闭”原则。
由于简单工厂模式使用静态方法作为工厂方法,而静态方法无法由子类继承,因此工厂角色无法形成基于继承的等级结构。这一缺点会在工厂方法模式中得到克服。
 
1.1.4.7 简单工厂模式在Java中的应用
DateFormat与简单工厂模式
SAX2库中的XMLReaderFactory与简单工厂模式
 
1.1.4.8 女娲捏土造人
女娲需要用土造出一个个的人,这就是简单工厂模式的应用,类图如下:
点击在新窗口查看全图

 
女娲是工厂角色,人是抽象产品角色,张三李四是产品。具体实现就不在给出了,参看园丁生产水果的例子
1.2 工厂方法(Factory Method)模式
 
    工厂方法模式是类的创建模式,又叫虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。
    工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中。
 
1.2.1 工厂方法模式的引进
   
工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。下面是工厂方法模式的缩略类图:
点击在新窗口查看全图

 
  
  在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做。这个核心工厂则变为抽象工厂角色,仅负责给出具工厂子类必须实现的接口,而不接触哪一产品创建的细节。
    这种抽象的结果,使这种工厂方法模式可以用来允许系统不修改具体工厂角色的情况下引进新产品,这一特点无疑使得工厂模式具有超过简单工厂模式的优越性。
 
1.2.2 工厂方法模式的结构
   
在工厂方法模式中,一般都有一个平行的等级结构,也就是说工厂和产品是对应的的。抽象工厂对应抽象产品,具体工厂对应具体产品。简单的示意图如下:
点击在新窗口查看全图
 
   
从上图可以看出,工厂方法模式的系统涉及到了以下角色:
    抽象工厂角色:与应用程序无关,任何在模式中创建对象的工厂必须实现这个接口。
    具体工厂角色:实现了抽象工厂接口的具体Java类,含有与引用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。
    抽象产品角色:工厂方法所创建产品对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
    具体产品角色:这个角色实现了抽象产品角色所声名的接口。工厂方法所创建的每个具体产品对象都是某个具体产品角色的实例。
 
1.2.3 工厂方法模式在农场系统中的实现
 
1.2.3.1 背景
    在简单工厂模式中,有个全能的园丁,控制所有作物的种植、生长和收获。现在农场规模变大了,管理更加专业化了。过去全能的园丁没有了,每一种作物都有专门的园丁管理,形成了规模化和专业化生产。
 
1.2.3.2 系统设计机构图
点击在新窗口查看全图
 
1.2.3.3 实现源码
 
1.2.3.3.1 水果产品接口Fruit.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  水果接口
 */
public interface Fruit {
    /**
     * 种植
     */
    void plant();
    /**
     * 生长
     */
    void grow();
    /**
     * 收获
     */
    void harvest();
}
 
1.2.3.3.2 具体产品苹果Apple.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  水果工厂的产品:苹果
 */
public class Apple implements Fruit {
    private int treeAge;
    /**
     * 种植
     */
    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.");
    }
    /**
     * @return 返回树龄
     */
    public int getTreeAge() {
        return treeAge;
    }
    /**
     * 设置树龄
     */
    public void setTreeAge(int treeAge) {
        this.treeAge = treeAge;
    }
}

1.2.3.3.3 具体产品葡萄:Grape.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  水果工厂的产品:葡萄
 */
public class Grape implements Fruit {
    private boolean seedless;   //是否有籽
    /**
     * 种植
     */
    public void plant() {
        System.out.println("Grape has been planted.");
    }
    /**
     * 生长
     */
    public void grow() {
        System.out.println("Grape is growing...");
    }
    /**
     * 收获
     */
    public void harvest() {
        System.out.println("Grape has been harvested.");
    }
    /**
     * @return 是否有籽
     */
    public boolean getSeedless() {
        return seedless;
    }
    /**
     * 有无籽的赋值方法
     */
    public void setSeedless(boolean seedless) {
        this.seedless = seedless;
    }
    /**
     * 辅助方法
     */
    public static void log(String msg) {
        System.out.println(msg);
    }
}

1.2.3.3.4 具体产品草莓:Strawberry.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  水果工厂的产品:草莓
 */
public class Strawberry implements Fruit {
    /**
     * 生长
     */
    public void grow() {
        System.out.println("Strawberry is growing...");
    }
    /**
     * 收获
     */
    public void harvest() {
        System.out.println("Strawberry has been harvested.");
    }
    /**
     * 种植
     */
    public void plant() {
        System.out.println("Strawberry has been planted.");
    }
    /**
     * 辅助方法
     */
    public static void log(String msg) {
        System.out.println(msg);
    }
}
 
1.2.3.3.5 水果工厂接口:FruitGardener.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  水果工厂接口
 */
public interface FruitGardener {
    /**
     * 工厂方法
     *
     * @return 水果
     */
    public Fruit factory();
}
 
1.2.3.3.6 苹果工厂:AppleGardener.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  苹果工厂方法
 */
public class AppleGardener implements FruitGardener {
    /**
     * 工厂方法
     *
     * @return 苹果
     */
    public Fruit factory() {
        Fruit f = new Apple();
        System.out.println("水果工厂(AppletGardener)成功创建一个水果:苹果!");
        return f;
    }
}
 
1.2.3.3.7 葡萄工厂:GrapeGardener.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  添加说明
 */
public class GrapeGardener implements FruitGardener {
    /**
     * 工厂方法
     *
     * @return 葡萄
     */
    public Fruit factory() {
        Fruit f = new Grape();
        System.out.println("水果工厂(GrapeGardener)成功创建一个水果:葡萄!");
        return f;
    }
}
 
1.2.3.3.8 草莓工厂:StrawberryGardener.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  添加说明
 */
public class StrawberryGardener implements FruitGardener {
    /**
     * 工厂方法
     *
     * @return 草莓
     */
    public Fruit factory() {
        Fruit f = new Strawberry();
        System.out.println("水果工厂(StrawberryGardener)成功创建一个水果:草莓!");
        return f;
    }
}
 
1.2.3.3.9 测试类(客户端):TestApp.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--工厂方法模式--一般性模式(农场应用)
 * ReadMe:  测试类(客户端)
 */
public class TestApp {
    private FruitGardener f1, f2, f3;
    private Fruit p1, p2, p3;
    private void test() {
        //实力化水果工厂
        f1 = new AppleGardener();
        f2 = new GrapeGardener();
        f3 = new StrawberryGardener();
        //从水果工厂生产水果
        p1 = f1.factory();
        p2 = f2.factory();
        p3 = f3.factory();
    }
    public static void main(String args[]) {
        TestApp test = new TestApp();
        test.test();
    }
}
 
1.2.3.3.10 测试运行结果
    水果工厂(AppletGardener)成功创建一个水果:苹果!
    水果工厂(GrapeGardener)成功创建一个水果:葡萄!
    水果工厂(StrawberryGardener)成功创建一个水果:草莓!
    Process finished with exit code 0
 
1.2.3.4 关于工厂方法模式的实现
   在下面我简单说说一些实现方式,不做详细分析了。
 1.使用java接口或者java抽象类
 2.使用多个工厂方法
 3.产品循环使用
 4.多态性的丧失和模式的退化,主要体现在工厂方法创建对象、工厂方法返回的类型、工厂等级结构三个方面。
 
1.2.3.5 女娲举绳造人
 
   女娲举绳造人是工厂方法模式的一个实例。下面仅仅给出设计图如下,具体编码请您自己实现。
点击在新窗口查看全图
 
 
  
1.3 抽象工厂(Abstract Factory)模式
    抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品具体类型的情况下,创建多个产品族中的产品对象。这就是抽象工厂模式的用意。
    每个模式都是针对一定问题的解决方案。抽象工厂模式面对的问题是多产品等级结构的系统设计。
    在学习抽象工厂具体实例之前,应该明白两个重要的概念:产品族和产品等级。
    产品族:是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如AMD的CPU和ADM芯片的主板,组成一个家族。Intel的CPU和Intel芯片的主板,又组成一个家族。而这两个家族都来自于两个产品等级:CPU,主板。一个等级结构是由相同的结构的产品组成,示意图如下:
点击在新窗口查看全图

 
   
理解这个产品结构是理解抽象工厂模式的关键所在,所以我不惜花费时间来画此图。如果领悟不到此图的含义,就无法区分工厂方法模式和抽象工厂模式的区别。
    从上图可以看出,抽象工厂模式的每个工厂创造出来的都是一族产品,而不是一个或者一组。组是可以随意组合的!其实两个就这点点差别,呵呵,估计现在你已经差不多明白了抽象工厂模式的含义。不废话了,看个例子,真相将大白于天下!
 
1.3.1 抽象工厂模式在农场中的实现

1.3.1.1 背景

    聪明的农场主总是让自己的庄园越来越有价值,“农场”在经历了简单工厂模式和工厂模式后,不断的扩大生产。如今,再次面临新的大发展,一项重要的工作就是引进塑料大棚技术,在大棚里种植热带(Tropical)和亚热带(Northern)的水果和蔬菜,用以满足市场需求,获取更大的利益。

1.3.1.2 产品角色图

    经过分析,对产品角色进行分析得出下图
点击在新窗口查看全图

 
1.3.1.3 系统设计

    经过分析,所谓的各个园丁其实就是工厂角色,而蔬菜和水果则是产品角色。将抽象工厂模式用于农场中,系统设计图如下:
 
点击在新窗口查看全图

 
1.3.1.4 实现源码

1.3.1.4.1 抽象工厂:Gardener.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  抽象工厂角色:工厂接口
 */
public interface Gardener {
    public Fruit createFruit(String name);
    public Veggie createVeggie(String name);
}
 
1.3.1.4.2 抽象水果产品:Fruit.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  抽象产品角色:水果接口
 */
public interface Fruit {
}
 
1.3.1.4.3 抽象蔬菜产品:Veggie.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  抽象产品角色:蔬菜接口
 */
public interface Veggie {
}
 
1.3.1.4.4 热带水果:TropicalFruit.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  具体产品角色:热带水果
 */
public class TropicalFruit implements Fruit {
    private String name;
    public TropicalFruit(String name) {
        System.out.println("热带工厂为您创建了:热带水果-"+name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
 
1.3.1.4.5 热带蔬菜:TropicalVeggie.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  具体产品角色:热带蔬菜
 */
public class TropicalVeggie implements Veggie {
    private String name;
    public TropicalVeggie(String name) {
        System.out.println("热带工厂为您创建了:热带水果-"+name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
 
1.3.1.4.6 亚热带水果:NorthernFruit.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  具体产品角色:亚热带水果
 */
public class NorthernFruit implements Fruit {
    private String name;
    public NorthernFruit(String name) {
        System.out.println("亚热带工厂为您创建了:亚热带水果-"+name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

1.3.1.4.7 亚热带蔬菜:NorthernVeggie.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  具体产品角色:亚热带蔬菜
 */
public class NorthernVeggie implements Veggie {
    private String name;
    public NorthernVeggie(String name) {
        System.out.println("亚热带工厂为您创建了:亚热带蔬菜-"+name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
 
1.3.1.4.8 热带工厂:TropicalGardener.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  具体工厂角色:热带工厂
 */
public class TropicalGardener implements Gardener {
    public Fruit createFruit(String name) {
        return new TropicalFruit(name);
    }
    public Veggie createVeggie(String name) {
        return new TropicalVeggie(name);
    }
}
 
1.3.1.4.9 亚热带工厂:NorthernGardener.java
/**
 * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  具体工厂角色:亚热带工厂
 */
public class NorthernGardener implements Gardener {
    public Fruit createFruit(String name) {
        return new NorthernFruit(name);
    }
    public Veggie createVeggie(String name) {
        return new NorthernVeggie(name);
    }
}

 
1.3.1.4.10 测试类(客户端):TestApp.java
/**
  * 《Java与模式》(--阎宏博士著)读书笔记
 * 工厂模式--抽象工厂模式--一般性模式(农场应用)
 * ReadMe:  测试类(客户端)
 */
public class TestApp {
    private void test(){
        Veggie tv,nv;
        Fruit tf,nf;
        TropicalGardener tg=new TropicalGardener();
        NorthernGardener ng=new NorthernGardener();
        tv=tg.createVeggie("热带菜叶");
        nv=ng.createVeggie("东北甜菜");
        tf=tg.createFruit("海南椰子");
        nf=ng.createFruit("雪梨");
    }
    public static void main(String args[]){
        TestApp test=new TestApp();
        test.test();
    }
}
 
1.3.1.4.11 测试运行结果
   
热带工厂为您创建了:热带水果-热带菜叶
    亚热带工厂为您创建了:亚热带蔬菜-东北甜菜
    热带工厂为您创建了:热带水果-海南椰子
    亚热带工厂为您创建了:亚热带水果-雪梨
    Process finished with exit code 0
    看完设计图和源码,原理已经很清楚了,这个模式应用很灵活,猴交给你了,看你怎么玩它!哈哈哈哈。。。。
1.3.1.5 女娲举绳造万物
   
女娲举绳造物的故事很适合在这里举例子,女娲的绳子按照阴阳划分,产品则按人、兽划分。将抽象工厂模式用于女娲造万物的模拟系统设计中。系统设计图如下:
点击在新窗口查看全图
设计题目:农夫果园 一个农场,专门种植销售各类水果,在这个系统中需要描述下列水果: 葡萄:Grape 草莓:Strawberry 苹果:Apple 水果与其他的植物有很大的不同,水果最终是可以采摘食用的。那么一个自然的做法就是建立一个各种水果都适用的接口,以便与农场里的其他植物区分开。水果接口规定出所有的水果都必须实现的接口,包括任何水果必须具备的方法:种植plant(),生长grow(),收获harvest()。 Apple类是水果中的一种,因此它实现了水果接口所声明的所有方法。另外,由于苹果是多年生植物,因此多出一个treeAge性质,描述苹果树的树龄。 Grape类是水果类的一种,也实现Fruit接口中所声明的所有方法。但由于葡萄分为有籽和无籽的两种,因此比通常的水果多出一个seedless性质。 Strawberry类也是水果的一种,也实现了Fruit接口。 农场的园丁也是系统的一部分,自然要由一个合适的类来代表。这个类就是FruitGardener,它会根据农场老板的要求,使用factory()方法创建出不同的水果对象,比如苹果(Apple),葡萄(Grape)或草莓(Strawberry)的实例。而如果接到不合法的要求,会提示错误。 农场的市场调查员也是系统的一部分,也需要一个类代表,这个类是MarketInquirer,它通过inquire()调查今年市场上哪一种水果热销。 农场的老板也是系统的一部分,仍需要一个类来代表,这个类是FruitBoss,他会根据市场调查员的反馈信息,通知农场的园丁今年种植哪种水果。 要求:请你根据上述系统需求,用Java语言设计这个农场系统,发挥你的想象力吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值