使用工厂类的作用
- creates objects without exposing the instantiation logic to the client.
这点是使用工厂模式的主要目的。当client需要一个类的实例时,它并不需要自己去实例化那个类,而是交给工厂去实例化。这样client就不需要知道这个类是怎么实例化的了。
这样对象的使用者和对象本身就解耦合了。
- refers to the newly created object through a common interface The implementation is really simple
如何实现
- The client needs a product, but instead of creating it directly using the new operator, it asks the factory object (通常就是个工厂类)for a new product, providing the information about the type of object it needs.
- The factory instantiates a new concrete product and then returns to the client the newly created product(casted to abstract product class).
- The client uses the products as abstract products without being aware about their concrete implementation.
需要注意的是,客户端既不知道,也不关心被实例化的类是什么,而只是得到了一个抽象类。而工厂类本身常常是一个Singleton的类,即工厂类不允许被实例化,而是提供静态方法。
最简单的工厂
public class ProductFactory{
public static Product createProduct(String ProductID){
if (id==ID1)
return new OneProduct();
if (id==ID2) return
return new AnotherProduct();
... // so on for the other Ids
return null; //if the id doesn't have any of the expected values
}
...
}
上例的问题是,每次新增一个新product的时候就需要修改工厂类。为了解决这个问题,工厂需要做一下改变。
更灵活的工厂类
class ProductFactory
{
private HashMap m_RegisteredProducts = new HashMap();
public void registerProduct (String productID, Class productClass)
{
m_RegisteredProducts.put(productID, productClass);
}
public Product createProduct(String productID)
{
Class productClass = (Class)m_RegisteredProducts.get(productID);
Constructor productConstructor = productClass.getDeclaredConstructor(new Class[] { String.class });
//其实这里已经使用了反射。首先使用反射得到了这个类的构造函数。然后使用构造函数实例化这个对象并返回。
return (Product)productConstructor.newInstance(new Object[] { });
}
}
上例的解决方法是,提供一个注册产品的方法。每个注册过的产品都会被放到Map中,且存储productID和product class type。只要是注册过的产品,工厂类就可以实例化该产品。
但是又一个问题:我们必须在调用工厂前完成所有product的注册。如果注册product的代码在调用工厂之后,则会找不到想实例化的类。
这里继续使用反射可以解决问题,大家参考原文吧。
不过我觉得就用noob factory挺好的。后面的方法虽然灵活,但是逻辑过于分散。把class creation都放在factory class里改起来简单。
如果不想使用反射,我们需要的是让每个类自己解决注册的问题,而不是在工厂里注册:
abstract class Product {
public abstract Product createProduct();
}
class OneProduct extends Product {
static // 静态方法在class被JVM load时就会执行,因此一定会在使用工厂类之前被注册。
{
ProductFactory.instance().registerProduct("ID1", new OneProduct());
}
public OneProduct createProduct() {
return new OneProduct();
}
}
class ProductFactory {
public void registerProduct(String productID, Product p) {
m_RegisteredProducts.put(productID, p);
}
public Product createProduct(String productID) {
((Product) m_RegisteredProducts.get(productID)).createProduct();
// 所以不是工厂创建的concrete class
// 而是调用class中的createProduct方法。注意这里没有使用构造函数来实例化对象,而是使用了专门写的createProduct方法。
}
}