工廠方法的解題思路是采用無為而治的方式,即自己不知道具體如何實作,把它延遲到子類實作。
1、定義
定義一個用于建立對象的接口,讓子類決定執行個體化哪個具體類。
2、使用場景
在任何需要生成複雜對象的地方,都可以使用工廠方法模式。
3、UML圖
- Product:抽象産品。
- ConcreteProduct:具體産品
- Factory:建立器,抽象工廠,申明建立Product的工廠方法。
- ConcreteFactory:具體工廠,實作具體的業務邏輯。
4、示例代碼
public abstract class Product {
}
public class ConcreteProduct extends Product {
}
public abstract class Factory {
public abstract Product createProduct();
//有時在一些方法中需要調用工廠方法來擷取 Product 對象
public void someOperation() {
Product product = createProduct();
}
}
public class ConcreteFactory extends Factory {
@Override
public Product createProduct() {
return new ConcreteProduct();
}
}
對于createProduct()方法,需要哪個産品就生産哪個産品,但有時也可以使用反射的方式更簡潔地生産具體的産品對象。
反射實作:
public abstract class Factory {
public abstract <T extends Product> T createProduct(Class<T> cls);
}
public class ConcreteFactory extends Factory {
@Override
public <T extends Product> T createProduct(Class<T> cls) {
Product p = null;
try {
p = (Product) Class.forName(cls.getName()).newInstance();
} catch(Exception e) {
e.printStackTrace();
}
return (T) p;
}
}
5、簡單工廠/靜态工廠
抽象出抽象工廠類 Factory 來,通常的情況是有多個不同的具體工廠實作。以上隻是實作了一個具體工廠concreteFactory,但通常一般還可能定義ConcreteFactoryA,ConcreteFactoryB …等,以産生不同的産品。這種我們稱為多工廠方法模式。
如果我們确定我們的工廠類隻有一個的時候,可以将其簡化掉,将對應的工廠方法改為靜态方法,那這種情況就變成了簡單工廠/靜态工廠了,它是工廠方法的一個弱化版本。
public class Factory {
public static Product createProduct() {
return new ConcreteProduct();
}
}
6、Java源碼中的實作
java中的 List , Set 就應用了工廠方法模式來擷取 Iterator。它們都實作了 Iterable 接口,來生産具體的 Iterator。
1、定義生産 Iterator 的接口
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator<T> iterator();
//...
}
2、 ArrayList 生産具體的 Iterator 的實作
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
//ArrayList 生産具體的 Iterator 的實作
public Iterator<E> iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
//...
}
//...
}
3、HashSet生産具體的 Iterator 的實作
public class HashSet<E> extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
public Iterator<E> iterator() {
return map.keySet().iterator();
}
}