看《Java与模式》时,发现一个理解上的问题:说工厂方法模式可能解决简单工厂方法的不足,不过我的理解是工厂方法模式把原来的问题抛给客户端而没有真正解决掉。
先看简单工厂模式的示例代码。
- Java code
class Factory{ static Product createProduct(String type) { if(type.equalsIgnoreCase("apple")) { return new AppleProduct(); }else if(type.equalsIgnoreCase("grape")) { return new GrapeProduct(); }else { throw new IllegalArgumentException("Not type corresponding"); } } } class Client_SimpleFactoryMethod { public static void main(String[] args) { String type = "grape"; Product p = Factory.createProduct(type); } } interface Product{} class AppleProduct implements Product{} class GrapeProduct implements Product{}
它的缺点是如果有新产品时,Factory类中createProduct方法应该做相应调整以包含新产品类的加入。哪新加了产品类BananaProduct,我们得给createProduct方法新加一个分支:
else if(type.equalsIgnoreCase("banana")) {
return new BananaProduct();
}
这样不好, 因为这样的处理违背了“开闭”原则。
为了解决这个问题,书中说引入工厂方法模式就可以了。
于是新加了每个产品类对应的工厂
- Java code
interface ProduectFactory{ Product createProduct(); } class AppleProduectFactory implements ProduectFactory{ public Product createProduct() { return new AppleProduct(); } } class GrapeProduectFactory implements ProduectFactory{ public Product createProduct() { return new GrapeProduct(); } } class Client_FactoryMethod { public static void main(String[] args) { String type = "grape"; ProduectFactory produectFactory=null; if(type.equalsIgnoreCase("apple")) { produectFactory = new AppleProduectFactory(); }else if(type.equalsIgnoreCase("grape")) { produectFactory = new GrapeProduectFactory(); } Product p = produectFactory.createProduct(); } }
对比上面的简单工厂方法,所不同的是,上面Client_SimpleFactoryMethod里的p的生成,是由Factory类的createProduct方法来据type种类判断具体生成哪种Product(直接生成);而在Client_FactoryMethod中的main里,先据type生成一个
ProduectFactory实现,再由这个ProduectFactory生成一个具体的Product。
问题是, 新产品BananaProduct引入时,工厂这边新加一个BananaProductFactory没问题,而客户端得加一个相应的判断分支。看来不厚道啊,相当于把问题推给客户端。
我知道,上面我的理解有偏差的地方,工厂模式的价值不会这个“偏差”而有所降低,请问理解的偏差在哪?
------解决方案--------------------
客户端自己知道所用的是哪个productFactory,所以没有判断。譬如你是苹果工厂,那么
- C/C++ code
class Client_FactoryMethod { public static void main(String[] args) { ProduectFactory produectFactory= new AppleProduectFactory(); Product p = produectFactory.createProduct(); } }
------解决方案--------------------
lz应该看到一点就是哪里需要修改,简单工厂方法里面createProduct()在有新产品的时候需要增加一个判断,违背了开闭原则
但是工厂模式里面有新产品的时候增加一个类,属于扩展范畴
而且在每个客户端,它是自己知道需要什么类型,也就是需要什么类型的就生成一个什么样的产品,1楼的代码很好的诠释了这一点。
另外,lz的类声明别带下划线