在任何需要生成复杂对象的地方,都可以使用工厂方法模式,复杂对象适合使用工厂方法模式,用 new 就可以完成创建的对象无需使用工厂方法模式。
优点:降低了对象之间的耦合度,工厂模式依赖于抽象的架构,其将实例化的任务交由子类去完成,有非常好的扩展性。 缺点:每次为工厂方法添加新的产品时就要编写一个新的产品类,同还要引入抽象层,必然会导致代码类结构的复杂化。
工厂方法模式的通用模式代码如下: 1. 抽象工厂方法(核心),具体生产什么由子类去实现:
public abstract class Factory {
public abstract Product createProduct();
}
public class ConcreteFactory extends Factory{
@Override
public Product createProduct() {
return new ConcreteProductA(); // 返回具体的产品对象
//return new ConcreteProductB(); // 返回具体的产品对象
}
}
public abstract class Product {
public abstract void method();
}
public class ConcreteProductA extends Product {
@Override
public void method() {
System.out.println("ConcreteProductA method");
}
}
public class ConcreteProductB extends Product {
@Override
public void method() {
System.out.println("ConcreteProductB method");
}
}
@Test
public void factoryTest() throws Exception {
Factory factory = new ConcreteFactory();
Product product = factory.createProduct();
product.method();
}
输出:ConcreteProductA method
这种方式比较常见,需要哪个就生产哪个,有时候还可以利用反射的方式更加简洁地来生产具体产品对象,此时,需要在工厂方法的参数列表中传入一个 Class 类来决定是哪一个产品类:
public abstract class Factory {
/**
* @param clz 产品对象类类型
* @param <T> 具体的产品对象
* @return
*/
public abstract <T extends Product> T createProduct(Class<T> clz);
}
对应的具体工厂类则通过反射获取类的实例即可:
public class ConcreteFactory extends Factory{
@Override
public <T extends Product> T createProduct(Class<T> clz) {
Product p = null;
try {
p = (Product) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) p;
}
}
再看一下测试代码的实现:
@Test
public void factoryTest() throws Exception {
Factory factory = new ConcreteFactory();
Product product = factory.createProduct(ConcreteProductA.class);
product.method();
Product product = factory.createProduct(ConcreteProductA.class);
product.method();
}
输出: ConcreteProductA method ConcreteProductB method
需要哪个类的对象传入哪一个类即可,这种方法比较简洁、动态。如果不喜欢这一种,也可以尝试为每一个产品都定义一个具体的工厂,各司其职,像拥有多个工厂的方式我们称为多工厂方法模式,同样当我们的工厂类只有一个的时候,我们还可以简化掉抽象类,只需要将对应的工厂方法给为静态方法即可:
public class Factory {
public static Product createProduct() {
return new ConcreteProductA();
}
}
工厂方法模式应用很广泛,开发中使用到的数据结构中就隐藏着对工厂方法模式的应用,例如 List、Set,List、Set 继承自 Collection 接口,而 Collection 接口继承于 Iterable 接口:
public interface Iterable<T> {
Iterator<T> iterator();
}
这意味着 List、Set 接口也会继承 iterator() 方法,下面以 ArrayList 为例进行分析: ArrayList 中 iterator() 方法的实现就是构造并返回一个迭代器对象:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
public Iterator<E> iterator() {
return new Itr();
}
// 迭代器
private class Itr implements Iterator<E> {
protected int limit = java.util.ArrayList.this.size;
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor < limit;
}
@SuppressWarnings("unchecked")
public E next() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
int i = cursor;
if (i >= limit)
throw new NoSuchElementException();
Object[] elementData = java.util.ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
try {
java.util.ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
limit--;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
// 代码省略
}
// 代码省略
}
其中的 iterator() 方法其实就相当于一个工厂方法,专为 new 对象而生,构造并返回一个具体的迭代器。
其实Android中对工厂方法模式的应用更多,先看如下代码:
public class AActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(new LinearLayout(this));
}
}
实际上,onCreate方法就相当于一个工厂方法,因为LinearLayout是一个ViewGroup,而ViewGroup又继承于View,简单地说,所有控件都是View的子类。在AActivity的onCreate方法中构造一个View对象,并设置为当前的ContentView返回给framework处理,如果现在又有一个BActivity,这时又在onCreate方法中通过setContentView方法设置另外不同的View,这是不是一个工厂模式的结构呢,其实设计模式离我们非常近!!!