研究和使用创立性模式的必要性
面向对象的设计的目的之一,就是把责任进行划分,以分派给不同的对象。我们推荐这种划分责任的作法, 是因为它和封装(Encapsulation)和分派(Delegation)的精神是相符合的。创立性模式把对象的创立过程封装起来,使得创立实例的责任与使用实例的责任分割开, 并由专门的模块分管实例的创立,而系统在宏观上不再依靠于对象创立过程的细节。
所有面向对象的语言都有固定的创立对象的办法。爪哇语的办法就是使用new操作符。比如
StringBuffer s = new StringBuffer(1000);
就创立了一个对象s,其类型是StringBuffer。使用new操作符的短处是事先必须明确知道要实例化的类是什么, 而且实例化的责任往往与使用实例的责任不加区分。使用创立性模式将类实例化,首先不必事先知道每次是要实例化哪一个类, 其次把实例化的责任与使用实例的责任分割开来,可以弥补直接使用new操作符的短处。
而工厂模式就是专门负责将大量有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式。
工厂模式有几种形态
工厂模式有以下几种形态:
简单工厂(Simple Factory)模式
工厂方法(Factory Method)模式,又称多形性工厂(Polymorphic Factory)模式
抽象工厂(Abstract Factory)模式,又称工具箱(Kit或Toolkit)模式
介绍简单工厂模式
比如说,你有一个描述你的后花园的系统,在你的后花园里有各种的花,但还没有水果。你现在要往你的系统里引进一些新的类,用来描述下列的水果:
葡萄 Grapes
草莓 Strawberry
萍果 Apple
花和水果最大的不同,就是水果最终是可以采摘食用的。那么,很自然的作法就是建立一个各种水果都适用的接口,这样一来这些水果类作为相似的数据类型就可以和你的系统的其余部分,如各种的花有所不同,易于区分。
图1. Grape, Strawberry和Apple是拥有共同接口FruitIF的类。
package com.javapatterns.simplefactory;
public interface FruitIF {
void grow();
void harvest();
void plant();
String color = null;
String name = null;
}
代码清单1. 接口FruitIF的源代码。这个接口确定了水果类必备的方法:种植plant(),生长grow(), 以及收获harvest()。
package com.javapatterns.simplefactory;
public class Apple implements FruitIF
{
public void grow()
{
log("Apple is growing...");
}
public void harvest()
{
log("Apple has been harvested.");
}
public void plant()
{
log("Apple has been planted.");
}
public static void log(String msg)
{
System.out.PRintln(msg);
}
public int getTreeAge(){ return treeAge; }
public void setTreeAge(int treeAge){ this.treeAge = treeAge; }
private int treeAge;
}
代码清单2. 类Apple的源代码。萍果是多年生木本植物,因此具备树龄treeAge性质。
package com.javapatterns.simplefactory;
public class Grape implements FruitIF
{
public void grow()
{
log("Grape is growing...");
}
public void harvest()
{
log("Grape has been harvested.");
}
public void plant()
{
log("Grape has been planted.");
}
public static void log(String msg)
{
System.out.println(msg);
}
public boolean getSeedful()
{
return seedful;
}
public void setSeedful(boolean seedful)
{
this.seedful = seedful;
}
private boolean seedful;
}
代码清单3. 类Grape的源代码。葡萄分为有籽与无籽两种,因此具有seedful性质。