1. Factory Method 模式---------- 将实例的生成交给子类
》》 Factory 有“工厂”的意思。用 Template Method 模式来构建生成实例的工厂,这就是 Factory Method 模式。
》》 在 Factory Method 模式中,父类决定实例的生成方式,但并不决定所要生成的具体的类,具体的处理
全部交给子类负责。这样就将生成实例的框架( framework)和实际负责生成实例的类解耦。
2.示例程序:
》》 生成实例的框架(framework包)
加工处理(idcard 包)
》》
》》示例程序的类图:
1)、Product 类
》》 framework 包中的 Product 类是用来表示“产品”的类。在该类中仅声明了 use 抽象方法。use 方法的实现则被交给了 Product
类的子类负责。
在这个框架中,定义了产品是“任意的可以 use 的”东西
》》 代码清单:
public abstract class Product {
public abstract void use();
}
2)、Factory 类
》》 在 framework 包中的 Factory 类中,我们使用了 Template Method 模式。该类还声明了
用于“生成产品”的 createProduct 的抽象方法和用于“注册产品”的 registProduct
抽象方法。“生产产品”和“注册产品”的具体处理则被交给了 Factory 类的子类负责。
》》 在这个框架中,我们定义了工厂是用来“调用 create 方法生成 Product 实例”的。而
create 方法的实现是先调用 createProduct 生产产品,接着调用 registProduct 注册产品。
》》 具体的实现内容根据 Factory Method 模式适用的场景不同而不同。但是,只要是 Factory Method
模式,在生成实例时就一定会使用到 Template Method 模式。
》》代码清单:
public abstract class Factory {
public final Product create(String owner){
Product p = createProduct(owner);
registerProduct(p);
return p;
}
/**
* 生产产品
* @param owner
* @return
*/
protected abstract Product createProduct(String owner);
/**
* 注册产品
* @param product
*/
protected abstract void registerProduct(Product product);
}
3)、IDCard 类
》》 代码清单:
public class IDCard extends Product{
private String owner;
public IDCard(String owner){
System.out.println("制作"+owner+"的ID卡");
this.owner = owner;
}
public void use(){
System.out.println("使用"+owner+"的ID卡");
}
public String getOwner(){
return owner;
}
}
4)、IDCardFactory 类
》》 IDCardFactory 类实现了 createProduct 方法和 registerProduct 方法
》》 createProduct 方法通过生成 IDCard 的实例来“生产产品”
》》 registerProduct 方法通过将 IDCard 的 owner (持有人)保存到 owners 字段中来实现“注册产品”
》》代码清单:
import java.util.List;
import java.util.ArrayList;
public class IDCardFactory extends Factory {
private List owners = new ArrayList();
protected Product createProduct(String owner){
return new IDCard(owner);
}
protected void registerProduct(Product product){
owners.add(((IDCard)product).getOwner());
}
public List getOwners(){
return owners;
}
}
5)、Main 类
public class Main {
public static void main(String[] args){
Factory factory = new IDCardFactory();
Product card1 = factory.create("小明");
Product card2 = factory.create("小红");
Product card3 = factory.create("小刚");
card1.use();
card2.use();
card3.use();
}
6)、上面代码的执行效果:
3.Factory Method 模式中的登场角色
1)、Product(产品)
Product 角色属于框架这一方,是一个抽象类。它定义了在 Factory Method 模式中生成的那些实例所持有
的接口(API),但具体的处理则由子类 ConcreteProduct 角色决定。在示例程序中,由 Product 类扮演此角色。
2)、Creator(创建者)
Creator 角色属于框架这一方,它是负责生成 Product 角色的抽象类,但具体的处理则由子类
ConcreteProduct 角色决定。在实例程序中,由 Factory 类扮演此角色。
Creator 角色对于实际负责生成实例的 ConcreteCreator 角色一无所知,它唯一知道的就是,只要调用 Product
和生成实例的方法,就可以生成 Product 的实例。在示例程序中, createProduct 方法是用于生成实例的方法。
不用 new 关键字来生成实例,而是调用生成实例的专用方法来生成实例,这样就可以防止父类与其他具体类耦合。
3)、ConcreteProduct(具体的产品)
ConcreteProduct 角色属于具体加工这一方,它决定了具体的产品。在示例程序中,由 IDCard 类扮演此角色。
4)、ConcreteCreator(具体的创建者)
ConcreteCreator 角色属于具体加工这一方,它负责生成具体的产品。在示例程序中,由 IDCardFactory 类扮演
此角色。
4.扩展思路的要点
1)、框架与具体加工
我们分别学习了“框架”与“具体加工”这两方面的内容。它们分别被封装在 framework 包和 idcard 包中。
注意: framework 包不依赖于 idcard 包。
2)、生成实例----方法的三种实现方式
》》 在示例程序中,Factory 类的 createProduct 方法是抽象方法,也就是说需要在子类中实现该方法。
》》 createProduct 方法的实现方式一般有以下 3 种:
方式一:指定其为抽象方法
指定其为抽象方法。一旦将 createProduct 指定为抽象方法后,子类就必须实现该方法。如果
子类不实现该方法,编译器将会报告编译错误。这也是示例程序所采用的方式。
方式二:为其实现默认处理
为其实现默认处理。实现默认处理后,如果子类没有实现该方法,将进行默认处理。
class Factory{
public Product createProduct(String name){
return new Product(name);
}
...
}
不过,这时是使用 new 关键字创建出实例的,因此不能将 Product 类定义为抽象类。
方式三:在其中抛出异常
在其中抛出异常的方法。createProduct 方法的默认处理为抛出异常,这样一来,如果未在
子类中实现该方法,程序就会在运行时出错(报错,告知开发人员没有实现 createProduct 方法)
class Factory{
public Product createProduct(Stirng name){
throw new FactoryMethodRuntimeException();
}
}
不过,需要另外编写 FactoryMethodRuntimeException 异常类。
3)、使用模式与开发人员之间的沟通
》》不论是 Template Method 模式,还是 Factory Method 模式,在实际工作中使用时,都会让我们
感觉到比较困难。这是因为,如果仅阅读一个类的代码,是很难理解这个类的行为的。必须要理解父类中
所定义的处理的框架和它里面所使用的抽象方法,然后阅读代码,了解这些抽象方法在子类中的实现才行。
》》 通常,使用设计模式类时,必须要向必须要向维护这些类的开发人员正确地传达设计这些设计模式
的意图。否则,维护人员在修改设计时可能会违背设计者最初的意图。
这时,我们建议在程序注释中和开发文档中记录所使用的设计模式的名称和意图。
5.相关的设计模式
》》 Template Method 模式
Factory Method 模式是 Template Method 的典型应用。
》》 Singleton 模式
在多数情况下我们都可以将 Singleton 模式用于扮演 Creator 角色(或者是 ConcreteCreator 角色)
的类。这是因为在程序中没有必要存在多个 Creator 角色(或者是 ConcreteCreator 角色)的实例。
不过在示例程序中,我们并没有使用 Singleton 模式。
》》 Composite 模式
有时可以将 Composite 模式 用于 Product 角色(或者 ConcreteProduct 角色)
》》 Iterator 模式
有时,在 Iterator 模式中使用 iterator 方法生成 Iterator 的实例的时候会使用 Factory Method
模式。
6.总结:
》》 在设计模式中,多个类和接口扮演各自的角色,互相协作进行工作。在分析设计模式时,不应当将其中
一个类单独拿出来分析,必须着眼于类和接口之间的相互关系。