1.1概述
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。这就是工厂方法模式的定义。
得到一个类的子类的实例最常用的办法就是使用new运算符和该子类的构造方法,但是在某些情况下,用户可能不应该或无法使用这种办法来得到一个子类的实例,其原因是系统不允许用户代码和该类的子类形成耦合或者用户不知道该类有哪些子类可用。
例如,有一个笔芯类(PenCore),该类是一个抽象类。假设笔芯类有三个子类,分别是红笔芯类(RedPenCore)、蓝笔芯类(BluePenCore)、黑笔芯类(BlackPenCore),而系统设计的目的是为用户提供圆珠笔类(BallPen)的子类的实例,即含有笔芯的圆珠笔,也就是说系统想让用户使用圆珠笔类的子类的实例来得到笔芯类的子类的实例。
为此,在设计圆珠笔类的同时,决定让它依赖于笔芯类,并且提供了一个返回笔芯类对象的方法,比如:PenCore getPenCore();
但是圆珠笔类本身并不知道用户需要哪种颜色的笔芯,即不知道用户需要笔芯类的哪个子类的实例,因此圆珠笔类将getPenCore()方法设置为抽象方法,并将自己设置为抽象类,要求其子类重写(覆盖)getPenCore()方法,并使用getPenCore()方法返回笔芯类的一个特定子类的实例。比如,当用户需要蓝笔芯类的实例时,就不需要使用new运行符和蓝笔芯类的构造方法来来创建对象,代替地使用蓝笔芯类创建一个对象,该对象调用getPenCore()方法就可以为用户获得一个蓝笔芯类的实例,用户可以让这个实例调用有关方法写出蓝色的字了。具体示意类图如下图一所示:
图一:圆珠笔与笔芯示意类图
当系统准备为用户提供某个类的子类的实例,又不想让用户代码和该子类形成耦合时,就可以使用工厂方法模式来设计系统。工厂方法模式的关键是在一个接口或抽象类中定义一个抽象方法,该方法返回某个类的子类的实例,该抽象类或接口让其子类或实现该接口的类通过重写这个抽象方法返回某个子类的实例。
1.2模式的结构
工厂方法模式结构包括四种角色:
(1)抽象产品(Product):抽象类或接口,负责定义具体产品必须实现的方法;
(2)具体产品(ConcreteProduct):具体产品是一个类,如果Product是一个抽象类,那么具体产品是Product的子类;如果Product是一个接口,那么具体产品是实现Product接口的类;
(3)构造者(Creator):一个接口或抽象类。构造者负责定义一个称作工厂方法的抽象方法,该方法返回具体产品类的实例。
(4)具体构造者(COncreteCreator):如果构造者是一个抽象类,那么具体构造者就是构造者的子类;如果构造者是一个接口,那么具体构造者就是实现构造者接口的类。具体构造者重写工厂方法使该方法返回具体产品的实例。
工厂方法模式结构的类图如下图二所示:
图二:工厂方法模式的类图
1.3工厂方法模式的优点
(1)使用工厂方法可以让用户的代码和某个特定类的子类的代码解耦。
(2)工厂方法使用用户不必知道它所使用的对象是怎样被创建的,只需知道该对象有哪些方法即可。
1.4适合使用工厂方法模式的情景
(1)用户需要一个类的子类的实例,但不希望与该类的子类形成耦合。
(2)用户需要一个类的子类的实例,但用户不知道该类有哪些子类可用。
1.5工厂方法模式的使用
下面通过一个简单的实例,实现1.1概述中简单例子,具体如下:
首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图3所示:
图3 具体编写类与类图对应关系
(1)抽象产品(Product)
在1.1概述中提到的PenCore类是模式中的Product角色,PenCore类的代码如下:
package com.liuzhen.ten_factory;
public abstract class PenCore {
String color;
public abstract void writeWord(String s);
}
(2)具体产品(ConcreteProduct)
在1.1概述中提到的RedPenCore、BluePenCore和BlackPenCore类是三个具体产品角色,代码如下:
RedPenCore.java类
package com.liuzhen.ten_factory;
public class RedPenCore extends PenCore{
RedPenCore(){
color = "红色";
}
public void writeWord(String s){
System.out.println("写出"+color+"的字:"+s);
}
}
BluePenCore.java类
package com.liuzhen.ten_factory;
public class BluePenCore extends PenCore{
BluePenCore(){
color = "蓝色";
}
public void writeWord(String s){
System.out.println("写出"+color+"的字:"+s);
}
}
BlackPenCore.java类
package com.liuzhen.ten_factory;
public class BlackPenCore extends PenCore{
BlackPenCore(){
color = "黑色";
}
public void writeWord(String s){
System.out.println("写出"+color+"的字:"+s);
}
}
(3)构造者(Creator)
在1.1概述中提到的BallPen类是构造者角色,代码如下:
package com.liuzhen.ten_factory;
public abstract class BallPen {
BallPen(){
System.out.println("生产了一只装有"+getPenCore().color+"笔芯的圆珠笔");
}
public abstract PenCore getPenCore(); //工厂方法
}
(4)具体构造和(ConcreteCreator)
在1.1概述中提到的RedBallPen、BlueBallPen、BlackBallPen类是具体构造者角色,代码如下:
RedBallPen.java类
package com.liuzhen.ten_factory;
public class RedBallPen extends BallPen{
public PenCore getPenCore(){
return new RedPenCore();
}
}
BlueBallPen.java类
package com.liuzhen.ten_factory;
public class BlueBallPen extends BallPen{
public PenCore getPenCore(){
return new BluePenCore();
}
}
BlackBallPen.java类
package com.liuzhen.ten_factory;
public class BlackBallPen extends BallPen{
public PenCore getPenCore(){
return new BlackPenCore();
}
}
(5)具体使用
通过TenApplication类来具体实现上述相关类,来实现工厂方法模式的运用,其代码如下:
package com.liuzhen.ten_factory;
public class TenApplication {
public static void main(String args[]){
PenCore penCore;
BallPen ballPen = new BlueBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("您好,很高兴认识你");
ballPen = new RedBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("How are you");
ballPen = new BlackBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("nice to meet you");
}
}
运行结果如下:
生产了一只装有蓝色笔芯的圆珠笔
写出蓝色的字:您好,很高兴认识你
生产了一只装有红色笔芯的圆珠笔
写出红色的字:How are you
生产了一只装有黑色笔芯的圆珠笔
写出黑色的字:nice to meet you
参考资料:
1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5