设计模式之工厂模式(Factory)

工厂模式在应用中使用得也很广泛,他提供了一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

考虑一个动物类Animal,提供shout,eate,grow方法,并从这个抽象类派生具体的动物子类:Cow,Horse,Dog,Pig

最后通过Factory类实例化他们,Factory提供一个静态的方法getAnimalInstance,并传递一个字符串参数表示创建具体的

 

下面是java实现的代码例子:

import java.util.*; interface Animal{ // 动物在叫 public void shout(); // 动物在吃 public void eate(); // 动物在生长 public void grow(); } class Cow implements Animal{ public void shout(){ System.out.println("牛在哞哞叫"); } public void eate(){ System.out.println("牛在吃草"); } public void grow(){ System.out.println("牛在生长"); } } class Horse implements Animal{ public void shout(){ System.out.println("马在嘶鸣"); } public void eate(){ System.out.println("马在吃草"); } public void grow(){ System.out.println("马在生长"); } } class Pig implements Animal{ public void shout(){ System.out.println("猪在叫"); } public void eate(){ System.out.println("猪在吃食物"); } public void grow(){ System.out.println("猪在生长"); } } class Dog implements Animal{ public void shout(){ System.out.println("狗在汪汪叫"); } public void eate(){ System.out.println("狗在吃骨头"); } public void grow(){ System.out.println("狗在生长"); } } class Factory{ public static Animal getAnimalInstance(String type){ Animal an=null; if (type.equals("Dog")){ an = new Dog(); } else if (type.equals("Cow")){ an = new Cow(); } else if (type.equals("Horse")){ an = new Horse(); } else if (type.equals("Pig")){ an = new Pig(); } else{ System.out.println("没发现这个类型"); System.exit(1); } return an; } } public class FactoryDemo01 { public static void main(String[] args) { if (args.length<=0){ System.out.println("必须输入一个命令行参数"); System.exit(1); } Animal an = Factory.getAnimalInstance(args[0]); an.shout(); an.eate(); an.grow(); } } 

 

从上面的代码可以看到,要从工厂里生成一个具体的动物对象,只需向工厂的getAnimalInstance传递一个字符串参数即可

但是我们仔细再看一下Factory类的getAnimalInstance方法,当我们再派生一个Elephant 大象类时,我们又不得不以修改

Factory里的if - else 逻辑为代价!

兴奋的是java语言中提供的Class类的一个forName可以从一个字符串生成对应的类实例的能力,而C++是没有这个本事的,原因是java是解析执行的,而C++是编译型的语言,c++中怎么实现类似的功能呢?在以后的文章中再描述。

 

好了我们继续改进上面的代码,主要是改进Factory类的实现

class Factory{ public static Animal getAnimalInstance(String type){ Animal an=null; /**if (type.equals("Dog")){ an = new Dog(); } else if (type.equals("Cow")){ an = new Cow(); } else if (type.equals("Horse")){ an = new Horse(); } else if (type.equals("Pig")){ an = new Pig(); } else{ System.out.println("没发现这个类型"); System.exit(1); }*/ try{ an = (Animal)Class.forName(type).newInstance(); } catch(Exception e){ System.out.println("没发现这个类型"); System.exit(1); } return an; } } 

 

好了,在命令行里输入Dog,然后执行:

狗在汪汪叫

狗在吃骨头

狗在生长

 

好,这回解决了由于增加子类而不得不修改工厂的问题,在我们看来貌似已经十分的完美了,工厂模式做到这个程度总可以了吧?

别急,新的问题又产生了,客户的需求总是不断的改,功能不断的加,我们的子类不断的膨胀,子类越来越多,客户使用我们的工厂类时

对具体的子类比较难记,这时我们可以通过使用一个代号到具体的子类映射来解决这个问题,java中为我们提供了Properties这样的一个类

实际上这个类就是从我们的hashtable类派生而来的。

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

 

具体的改进代码我就不贴出来了,使用Properties后我们可以从xml之类的文件加载准备创建的类信息然后生成对应的类实例,

客户只需修改xml文件就可,方便至极@!

 

你可能感兴趣的:(设计模式之工厂模式(Factory))