工厂方法
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的
实例化延迟到其子类。
适用性
在下列情况下可以使用Factory Method模式:
• 当一个类不知道它所必须创建的对象的类的时候。
• 当一个类希望由它的子类来指定它所创建的对象的时候。
• 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类
是代理者这一信息局部化的时候。
工厂方法模式的结构
在工厂方法模式中,一般都有一个平行的等级结构,也就是说工厂和产品是对应的的。抽象工厂对应抽象产品,具体工厂对应具体产品。简单的示意图如下:
从上图可以看出,工厂方法模式的系统涉及到了以下角色:
抽象工厂角色:与应用程序无关,任何在模式中创建对象的工厂必须实现这个接口。
具体工厂角色:实现了抽象工厂接口的具体Java类,含有与引用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。
抽象产品角色:工厂方法所创建产品对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品角色:这个角色实现了抽象产品角色所声名的接口。工厂方法所创建的每个具体产品对象都是某个具体产品角色的实例。
应用场景示例:
简单工厂模式与工厂方法模式大PK
1. 结构复杂度
从这个角度比较,显然简单工厂模式要占优。简单工厂模式只需一个工厂类,而工厂方法模式的工厂类随着产品类个数增加而增加,这无疑会使类的个数越来越多,从而增加了结构的复杂程度。
2.代码复杂度
代码复杂度和结构复杂度是一对矛盾,既然简单工厂模式在结构方面相对简洁,那么它在代码方面肯定是比工厂方法模式复杂的了。简单工厂模式的工厂类随着产品类的增加需要增加很多方法(或代码),而工厂方法模式每个具体工厂类只完成单一任务,代码简洁。
3.客户端编程难度
工厂方法模式虽然在工厂类结构中引入了接口从而满足了OCP,但是在客户端编码中需要对工厂类进行实例化。而简单工厂模式的工厂类是个静态类,在客户端无需实例化,这无疑是个吸引人的优点。
4.管理上的难度
这是个关键的问题。
我们先谈扩展。众所周知,工厂方法模式完全满足OCP,即它有非常良好的扩展性。那是否就说明了简单工厂模式就没有扩展性呢?答案是否定的。简单工厂模式同样具备良好的扩展性——扩展的时候仅需要修改少量的代码(修改工厂类的代码)就可以满足扩展性的要求了。尽管这没有完全满足OCP,但笔者认为不需要太拘泥于设计理论,要知道,sun提供的java官方工具包中也有想到多没有满足OCP的例子啊(java.util.Calendar这个抽象类就不满足 OCP,具体原因大家可以分析下)。
然后我们从维护性的角度分析下。假如某个具体产品类需要进行一定的修改,很可能需要修改对应的工厂类。当同时需要修改多个产品类的时候,对工厂类的修改会变得相当麻烦。反而简单工厂没有这些麻烦,当多个产品类需要修改是,简单工厂模式仍然仅仅需要修改唯一的工厂类
Abstract Factory模式与Factory Method模式的主要区别:
1 Factory Method采用的是工厂类继承机制(生成子工厂类,重载该工厂方法,在重载的方法中生成目标对象)。而Abstract Factory强调的是对象组合机制,由在父工厂内定义不同的“子工厂”对象来负责不同的目标对象的创建。再深入一点理解:
2 Factory Method模式中,产品(目标对象)的使用者可能需要使用具体的子工厂来生成该产品;Abstract Factory模式则采用传参数的形式直接在父工厂内决定该产品对象应该由哪一个子工厂生产。也就是说,Abstract Factory模式中,跟客户打交道的只有抽象工厂与抽象产品,客户不需要知道产品由哪个工厂生产,也不需要知道被生产的是哪一种具体的产品。
3 Factory Method模式中,省城的对象产品只限定于某一类产品;Abstract Factory模式则可以提供多个生产接口生成多类产品
4 Abstract Factory模式Factory Method模式的更高层次的抽象,也更最具一般性。可以把Factory Method模式看作是Abstract Factory模式的一种特殊情况
简单一点说,Abstract Factory模式通过抽象工厂为客户(调用者)生成多类产品,抽象工厂负责管理子工厂对象,子工厂负责生成某一类具体的产品对象。
Jdk中工厂方法的应用:
1 java.util.collection提供的iterator对象
java list返回iterator和listiterator
AbstractList.java
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
。。。。。。
}
CopyOnWriteArrayList.java
public Iterator<E> iterator() {
return new COWIterator<E>(array(), 0);
}
AbstractlinkList.java
public Iterator iterator() {
return listIterator();
}
public ListIterator listIterator() {
return new LinkedListIterator(this, 0);
}
2.java.beans
public static Object instantiate(ClassLoader cls, String beanName) throws java.io.IOException, ClassNotFoundException {
return Beans.instantiate(cls, beanName, null, null);
}