创建模式:简单工厂模式(静态工厂方法)
描述:由一个工厂对象决定创建出哪一种产品类的实例。
工厂模式专门负责将大量有共同接口的类实例化。
抽象类/接口 |
工厂类--Creates---->子类/实现类
Fruit接口有三个方法:
public interface Fruit
{
void grow();
void harvest();
void plant();
}
苹果,草莓,葡萄都实现了这一接口,其中葡萄有有籽无籽之分(seedness:boolean),苹果有树的年龄属性(treeAge:int)。
//Grape
public class Grape implements Fruit
{
public void grow()
{
System.out.println("Grape is growing...");
}
public void harvest()
{
System.out.println("Grape has been harvested.");
}
public void plant()
{
System.out.println("Grape has been planted.");
}
public boolean getSeedless()
{
return seedless;
}
public void setSeedless(boolean seedless)
{
this.seedless = seedless;
}
private boolean seedless;
}
//Strawberry
public class Strawberry implements Fruit
{
public void grow()
{
System.out.println("Strawberry is growing...");
}
public void harvest()
{
System.out.println("Strawberry has been harvested.");
}
public void plant()
{
System.out.println("Strawberry has been planted.");
}
}
//Apple
public class Apple implements Fruit
{
public void grow()
{
System.out.println("Apple is growing...");
}
public void harvest()
{
System.out.println("Apple has been harvested.");
}
public void plant()
{
System.out.println("Apple has been planted.");
}
public int getTreeAge(){ return treeAge; }
public void setTreeAge(int treeAge){ this.treeAge = treeAge; }
private int treeAge;
}
FruitGardener为园丁类(工厂类):
public class FruitGardener
{
public static Fruit factory(String which) throws BadFruitException
{
if (which.equalsIgnoreCase("apple"))
{
return new Apple();
}
else if (which.equalsIgnoreCase("strawberry"))
{
return new Strawberry();
}
else if (which.equalsIgnoreCase("grape"))
{
return new Grape();
}
else
{
throw new BadFruitException("Bad fruit request");
}
}
}
可以看出园丁类提供了一个静态工厂方法,在客户端的调用下,这个方法创建客户端所需要的水果对象,如果客户端的请求是系统所不支持的,则工厂方法抛出异常。在使用时,客户端只需要调用FruitGardener的静态方法factory()即可。
工厂类角色:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑,由一个具体java类实现。
抽象产品角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或者它们共同拥有的接口。由一个JAVA接口或者JAVA抽象类实现。
具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例,由一个JAVA具体类实现。
public class Creator{
public static Product factory()
{
return new ConcreteProduct();
}
}
抽象产品角色的主要目的是给所有具体产品提供一个共同的类型,在最简单的情况下,可以简化为一个标识接口,所谓标识接口,就是没有声明任何方法的空接口。
每个工厂类可以有多于一个的工厂方法,分别负责创建不同的产品对象。
如果系统只有一个具体产品角色的话,抽象产品角色可以省略。
有些情况下,工厂角色可以由抽象角色扮演,典型的应用是java.text.DateFormat。
三个角色全部合并:抽象角色被省略,工厂角色可以与具体产品角色合并。
循环使用产品对象
循环使用一个产品对象:每一次客户端调用工厂方法时,工厂方法总是提供同一个对象,工厂对象可以使用一个属性来存储这个产品对象。
循环使用一组对象:使用一个聚集对象来存储这个才产品对象。
简单工厂模式的优点:模式的核心是工厂类,这个类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,而客户端可以免除直接创建产品对象的责任,而仅仅负责消费产品,实现了对责任的分割。
简单工厂模式的缺点:当产品类有复杂的多层次等级结构时,工厂类只有一个,只能以不变应万变。工厂类无所不能,一旦工厂类不能工作,整个系统都会受到影响。
一个类里的逻辑太多,使得系统扩展困难---->工厂方法模式中克服。
使用静态方法作为工厂方法,不能由子类继承,难于形成基于继承的等级结构--->工厂方法模式中克服。
简单工厂角色只在有限的程度上支持OCP:允许客户端相对独立于产品创建的过程,并且在系统中引入新产品的时候无须许该客户端,这一点支持OCP;但是,新产品引入到系统中去的时候,就需要修改工厂类,将必要的逻辑加入到工厂类中,这一点不支持OCP。
应用:java.text.DateFormat:getTimeInstance():DateFormat
public final static DateFormat getTimeInstance(){}
使用静态工厂方法将具体子类的实例化的工作隐藏起来,从而客户端不必考虑如何将具体子类实例化,因为抽象类DateFormat会提供它的合适的具体子类的实例。