转自:《Java 设计模式》2009年( 耿祥义 张跃平 著)
一,概括:
工厂方法模式(别名:虚拟构造)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。
二,引入
得到一个类的子类的实例最常用的办法使使用 new 运算符和 该子类的构造方法,但是在通常情况下系统不允许用户代码和该类的子类形成耦合或者用户不知道该类有哪些子类可用,比如有一个 抽象的 Car类,该类有两个子类 ,Porsche类 和 QQCar类,而系统希望用户用 Factory类的子类的实例 来得到 Car类 的子类的实例。
为此,在设计 Factory类 时,决定让它依赖于 Car类,并且提供了一个返回 Car对象的 方法,比如:public Car createCar();
但是,Factory类 本身并不知道用户需要哪种车,即不知道需要 Car类 的哪个子类的实例,因此需要将 createCar()方法 设置为 抽象方法,自然而然的 Factory类 也要为抽象类,这样我们就可以让其子类重写 createCar()方法,分别返回 Porsche类 和 QQCar类 的实例。于是,当用户需要 porsche类 的实例时,就不必使用 new运算符 和 Porsche类 的构造方法来创建对象,可以使用 Factory1类 创建一个对象,让该对象调用 createCar()方法 就可以为用户获得一个 Porsche类 的实例。
三,代码与类图
上述例子的代码:
package MM; abstract class Car { abstract public String getName(); abstract public void buyCar(); } class Porsche extends Car { public String getName() { return "porsche"; } public void buyCar() { System.out.printf("君 可 愿 尝 试 一 下 单 手 开 " + getName() + "! "); } } class QQCar extends Car { public String getName() { return "QQcar"; } public void buyCar() { System.out.printf("君 可 愿 尝 试 一 下 单 手 开 " + getName() + "! "); } } abstract class Factory { /* 每个 子类构造方法的第一条语句都是隐含地调用 super() 本来来说,如果在这个类中调用 Factory(),那么 createCar().getName() 就会出错, 但是抽象类是无法定义抽象类对象的,也就是说 new Factory() 这一句是不会出现的 所以,这个构造函数只会被子类调用,届时,createCar() 就被重载了,createCar().getName() 就正确了 */ public Factory() { System.out.printf("我们生产了一辆 " + createCar().getName() + ". "); } abstract public Car createCar(); } class Factory1 extends Factory { public Car createCar() { return new Porsche(); } } class Factory2 extends Factory { public Car createCar() { return new QQCar(); } } public class M { public static void main(String args[]) { Car c; Factory f; f = new Factory1(); c = f.createCar(); c.buyCar(); f = new Factory2(); c = f.createCar(); c.buyCar(); } }
类图:
(注: 由于找不到合适的箭头,这箭头就画的不标准了)
四,工厂方法模式的结构
① 抽象产品(Product): Car类
② 具体产品(ConcreteProduct): Porsche类 和 QQCar类
③ 构造者(Creator): Factory类
④ 具体构造者(ConcreteCreator): Factory1类 和 Factory2类
五,工厂方法模式的优缺点
优点:
① 扩展性好,支持实体类的扩充。
② 可以让用户的代码和某个特定类的子类的代码解耦
③ 用户无需知道所使用的对象是怎么创建的,只需知道该对象有哪些方法。
缺点:
同时定义抽象工厂(构造者)和 具体的工厂(具体构造者),增加了一个类层次结构,不适合用于简单问题的求解
六,工厂方法模式的使用场景
① 用户需要一个类的子类的实例,但不希望与该类的子类形成耦合
② 用户需要一个类的子类的实例,但用户不知道该类有哪些的子类可用
七,工厂方法模式的使用
用户在使用工厂方法模式时,只和抽象产品,构造者以及具体构造者打交道,用户只需了解抽象产品有哪些方法,不需要知道有哪些具体产品。
工厂方法模式的关键是 在一个接口或抽象类中定义一个 抽象方法(构造者),该方法返回某个类的子类的实例,该抽象类或接口 让其 子类或实现该接口的类(具体构造者) 通过重写这个抽象方法 返回某个子类的实例。
============ =========== ========= ========= ========= ====== ===== === == =
蝶恋花 宋代: 晏殊
槛菊愁烟兰泣露,罗幕轻寒,燕子双飞去。明月不谙离恨苦,斜光到晓穿朱户。
昨夜西风凋碧树,独上高楼,望尽天涯路。欲寄彩笺无尺素,山长水阔知何处?