您的位置:首页 > 其它

每天一个设计模式之Factory

2011-04-23 16:35 218 查看

使用工厂类的作用

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方法。
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: