例题:定义一个借口Fruit,内有grow()和pick()方法;
定义两个实现类Apple、Orange,通过new实例化他们。
分析1:缺点就是子类和父类必须紧紧结合,耦合度高。
解决: 新建一个工厂Factory进行实例化,返回Fruit实例,一定程度上降低了耦合度。
分析2:如果客户(main)要求既可以使用Apple对象,也可以使用Orange对象则无法通过工厂完成。
解决: 修改工厂Factory,在其初始化方法中加一个参数,做一下判定,然后在main方法中通过参数来确定返回具体的实例对象。
分析3:如果输入的参数错误,则会出现空指向异常。
解决: 在工厂里加一个判断,如果根据输入参数没有找到Fruit类型的对象,则输出提示信息。
分析4:如果现在扩充了一个子类樱桃Cherry,则要修改工厂(工厂中如果没有子类的判断,则无法使用子类)。
解决: 修改工厂,去掉了原来的参数值判断决定生成具体实例的方法,而是通过Class类去实例化。
分析5:在项目中可能有几十个类同时实现了同一个接口,那么此时用户如何知道已有的接口子类呢?
解决: 代号 → 子类的包.类名
要有一个文件列表,给用户列出全部的代号→一个具体子类的映射。
Map不行,因为参数是字符串不是对象,可以用java.util.Properties类,是Hashtable的子类。
setProperties("","");
不再用main方法参数返回查找实例,而是用一个新类InputData接收从键盘输入的数据。
BufferedReader buf
= new BufferedReader(new InputStreamReader(System.in));接收键盘数据。
String str=buf.readLine();读出数据给字符串对象str。
实现了用户在无法知道全部子类的问题,同时通过Properties保存了全部的子类信息,之后通过代码进行操作。
分析6:如果程序现在扩充了一个子类,还需要去修改main()方法中的代码。
解决: 通过文件保存Properties中的内容,以后修改文件即可,而不用去修改类。
在文件中保存一段数据,数据为对应的代号和包名.类名。
per.store(参数,参数); per.storeToXML(参数,参数);
从文件中读取properties中的属性:
Properties per =per.loadFromXMl(new FileInputStream(文件名.xml));
具体实现还需要新建一个新类Init,从文件中读取内容。
注意:
可能有读者觉得工厂设计过于复杂,而且没有用处,具体的用法需要通过大量的项目训练才能够彻底掌握工厂设计模式的好处。
如果一个接口需要一个工厂的话,那么如果有100个接口,则会出现100个工厂,程序的维护又会很困难。