每天一个设计模式之Factory

使用工厂类的作用

  • 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方法。
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值