(来源:http://www.cn.ibm.com/developerworks)
内容:
基本概念
简单分析
具体实施
后话:
参考资料
关于作者
刘湛 (jeru@163.net)
武汉大学信息与计算科学系学士
2001 年 9 月
在设计模式中,factory method也是比较简单的一个,但应用非常广泛,ejb,rmi,com,corba,swing中都可以看到此模式的影子,它是最重要的模式之一.在很多地方我们都会看到xxxfactory这样命名的类,那么,什么是factory method,为什么要用这个模式,如何用java语言来实现该模式,这就是本文想要带给大家的内容.
基本概念
factory method是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到factory method 模式了.简单说来,factory method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.factory method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将factory method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化
简单分析
图1是factory method 模式的结构图,这里提供了一些术语,让我们可以进行更方便的描述:
product: 需要创建的产品的抽象类.
concreteproduct: product的子类,一系列具体的产品.
creator: 抽象创建器接口,声明返回product类型对象的factory method.
concretecreator: 具体的创建器,重写creator中的factory method,返回concreteproduct类型的实例.
图1: factory method 模式结构
由此可以清楚的看出这样的平行对应关系: product <====> creator ; conreteproduct <====> conretecreator
抽象产品对应抽象创建器,具体产品对应具体创建器.这样做的好处是什么呢?为什么我们不直接用具体的产品和具体的创建器完成需求呢?实际上我们也可以这样做.但通过factory method模式来完成,客户(client)只需引用抽象的product和creater,对具体的concreteproduct和concretecreator可以毫不关心,这样做我们可以获得额外的好处:
首先客户端可以统一从抽象创建器获取产生的实例,creator的作用将client和产品创建过程分离开来,客户不用操心返回的是那一个具体的产品,也不用关心这些产品是如何创建的.同时,concreteproduct也被隐藏在product后面,conreteproduct继承了product的所有属性,并实现了product中定义的抽象方法,按照java中的对象造型(cast)原则,通过concretecreator产生的concreteproduct可以自动的上溯造型成product.这样一来,实质内容不同的concreteproduct就可以在形式上统一为product,通过creator提供给client来访问.
其次,当我们添加一个新的concretecreator时,由于creator所提供的接口不变,客户端程序不会有丝毫的改动,不会带来动一发而牵全身的灾难, 这就是良好封装性的体现.但如果直接用concreteproduct和concretecreator两个类是无论如何也做不到这点的. 优良的面向对象设计鼓励使用封装(encapsulation)和委托(delegation),而factory method模式就是使用了封装和委托的典型例子,这里封装是通过抽象创建器creator来体现的,而委托则是通过抽象创建器把创建对象的责任完全交给具体创建器concretecreator来体现的.
现在,请再回头看看基本概念中的那段话,开始也许觉得生涩难懂,现在是不是已经明朗化了很多.
下面让我们看看在 java 中如何实现factory method模式,进一步加深对它的认识.
具体实施
先说明一点,用factory method模式创建对象并不一定会让我们的代码更短,实事上往往更长,我们也使用了更多的类,真正的目的在于这样可以灵活的,有弹性的创建不确定的对象.而且,代码的可重用性提高了,客户端的应用简化了,客户程序的代码会大大减少,变的更具可读性.
标准实现: 这里我采用bruce eckel 用来描述oo思想的经典例子 shape.这样大家会比较熟悉一些.我完全按照图1中所定义的结构写了下面的一段演示代码.这段代码的作用是创建不同的shape实例,每个实例完成两个操作:draw和erase.具体的创建过程委托給shapefactory来完成.
1.a 首先定义一个抽象类shape,定义两个抽象的方法.
abstract class shape {
// 勾画shape
public abstract void draw();
// 擦去 shape
public abstract void erase();
public string name;
public shape(string aname){
name = aname;
}
}class circle extends shape {
public void draw() {
system.out.println("it will draw a circle.");
}
public void erase() {
system.out.println("it will erase a circle.");
}
// 构造函数
public circle(string aname){
super(aname);
}
}class square extends shape {
public void draw() {
system.out.println("it will draw a square.");
}
public void erase() {
system.out.println("it will erase a square.");
}
// 构造函数
public square(string aname){
super(aname);
}
}abstract class shapefactory {
protected abstract shape factorymethod(string aname);
// 在anoperation中定义shape的一系列行为
public void anoperation(string aname){
shape s = factorymethod(aname);
system.out.println("the current shape is: " + s.name);
s.draw();
s.erase();
}
}class circlefactory extends shapefactory {
// 重载factorymethod方法,返回circle对象
protected shape factorymethod(string aname) {
return new circle(aname + " (created by circlefactory)");
}
}class squarefactory extends shapefactory {
// 重载factorymethod方法,返回square对象
protected shape factorymethod(string aname) {
return new square(aname + " (created by squarefactory)");
}
}class nothisshape extends exception {
public nothisshape(string aname) {
super(aname);
}
}abstract class shapefactory {
private static shape s;
private shapefactory() {}
static shape factorymethod(string aname, string atype) throws nothisshape{
if (atype.compareto("square")==0)
return new square(aname);
else if (atype.compareto("circle")==0)
return new circle(aname);
else throw new nothisshape(atype);
}
// 在anoperation中定义shape的一系列行为
static void anoperation(string aname, string atype) throws nothisshape{
s = factorymethod(aname, atype);
system.out.println("the current shape is: " + s.name);
s.draw();
s.erase();
}
}Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器