工厂方法模式是类的创建模式,又叫虚拟构造子模式或者多态性工厂模式。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
ξ 13.1 引言
在一个系统中,如果产品角色是具有等级结构的,即由一个或多个抽象角色和多个具体角色构成树装结构。这个时候通常会按照产品的等级结构设计一个同结构的工厂等级结构,然后由相应的工厂角色创建相应的产品角色,如下图所示:
上图中左侧为工厂角色结构,右侧为产品角色结构。其中深蓝色为抽象角色,灰色为具体角色。可以看出,对于每一种具体产品,都有一种对应的具体工厂来创建。 图中蓝色箭头为继承关系,黑色箭头为创建关系。
ξ 13.2 工厂方法模式的结构
下图为工厂方法的示意性UML图,从图上可以看出,工厂模式涉及到四种角色:
① 抽象工厂角色:当然这个角色的是工厂方法模式的核心,它是与应用程序无关的。任何在模式中创建对象的工厂类必须实现这个接口。在上面的系统中,这个角色由java接口Creator扮演;在实际的系统中,这个角色也常常使用抽象java类实现;
② 具体工厂角色:担任这个角色的是实现了抽象工厂接口的具体java类。具体工厂角色含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象;
③ 抽象产品角色:工厂方法模式所创建的对象的基类,也就是产品对象的共同基类或者共同拥有的接口。在系统中,这个角色由java接口或者抽象类实现;
④ 具体产品角色:这个角色实现了抽象产品角色所声明的接口。工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。
ξ 13.3 工厂方法在农场系统中的实现
在这次的实例里面,园丁不再是一个全能的类,取代他的是一个抽象的园丁角色(抽象工厂角色),而针对不同的产品,通常会有对应的具体工厂角色,具体类图如下:
具体代码:
public interface FruitGardener
... {
public Fruit factory() ;
}
// 具体工厂角色
public class AppleGardener implements FruitGardener
... {
public Fruit factory()
...{
return new Apple() ;
}
}
public class StrawberryGardener implements FruitGardener
... {
public Fruit factory()
...{
return new Strawberry() ;
}
}
public class GrapeGardener implements FruitGardener
... {
public Fruit factory()
...{
return new Grape() ;
}
}
// 抽象产品角色
public interface Fruit
... {
public void grow();
public void harvest();
public void plant();
}
// 具体产品角色
public class Apple implements Fruit
... {
public void grow()
...{
System.out.println( "Apple:grow" ) ;
}
public void harvest()
...{
System.out.println( "Apple:havest" ) ;
}
public void plant()
...{
System.out.println( "Apple:plant" ) ;
}
private int treeAge ;
public int getTreeAge()
...{
return this.treeAge ;
}
public void setTreeAge( int treeAge )
...{
this.treeAge = treeAge ;
}
}
public class Strawberry implements Fruit
... {
public void grow()
...{
System.out.println( "Strawberry:grow" ) ;
}
public void harvest()
...{
System.out.println( "Strawberry:havest" ) ;
}
public void plant()
...{
System.out.println( "Strawberry:plant" ) ;
}
}
public class Grape implements Fruit
... {
private boolean seedless;
public void grow()
...{
System.out.println( "Grape:grow" ) ;
}
public void harvest()
...{
System.out.println( "Grape:havest" ) ;
}
public void plant()
...{
System.out.println( "Grape:plant" ) ;
}
public boolean getSeedless()
...{
return seedless ;
}
public void setSeedless(boolean seedless)
...{
this.seedless = seedless ;
}
}
ξ 13.5 Java语言中工厂方法的例子
第一个例子有些错误,不写了。
第二个例子是URL和URLConnection的例子:URL本身是一个工厂,它的工厂方法OpenConnection()返回一个抽象的URLConnection类,根据不同的URL,URLConnection的实例也将不同。
ξ 13.6工厂方法与其他模式的关系
参考模板方法、MVC、享元模式和备忘录模式。