Java设计模式:工厂模式
2016-07-24 19:32
435 查看
Java设计模式:工厂模式
【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/52015589工厂模式的意图:定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化。工厂方法把实例化的工作推迟到子类中去是实现。 工厂模式可以根据客户的需要,定义一个工厂类专门负责创建类的实例。
一、先来看一下普通的设计模式:
public interface FruitInterface{ public void Colour(); } public class Apple implements FruitInterface{ @Override public void Colour() { System.out.println("---苹果的颜色是红色的---"); } } public class Orange implements FruitInterface{ @Override public void Colour() { System.out.println("---橘子的颜色是黄色的---"); } } public class FruitTest { //客户端程序 public static void main(String[] args) { FruitInterface f = new Apple(); f.Colour(); } }上面的客户端程序Fruit f = new Apple();可以获得苹果的颜色,但若要获得橘子的颜色,就需要在客户端增加橘子的实例化代码,并显式的调用;这样并不利于后期的维护和管理;决解的方法是新建一个工厂,通过IF判断语句,根据客户端需要,实例化对应的对象,实现对颜色的统一管理。
二、新增加一个Factory作为过渡端,并通过过渡端取得接口的实例化对象,这个过渡端就是工厂类:
//工厂类,用于生产对象 public class Factory { public FruitInterface getColour(String key) { FruitInterface f = null;// 定义接口对象,通过过子类实例化 if ("Apple".equals(key)) { f = new Apple();// 通过Apple类实例化接口 } else if ("Orange".equals(key)) { f = new Orange();// 通过Orange类实例化接口 } return f; } }
//客户端程序 public class FruitTest { public static void main(String[] args) { //(1)普通设计模式,客户端需要显式的实现化对象 // FruitInterface f = new Apple(); // f.Colour(); //(2)工厂设计模式,客户端仅需要改变输入参数,增加新类时需要修改工厂类 Factory factory = new Factory(); FruitInterface colour = factory.getColour("Apple"); colour.Colour(); } }与普通的设计模式相比,工厂模式实例过程是在工厂类完成的,而不是在客户端的代码中实现的,客户端只需改变输入参数(改变参数Apple),即可获得对用的实例对象。通过工厂类,可以避免客户端显式的调用颜色这个方法,从而降低了客户端程序与产品对象的耦合。
三、继续改进:工厂类中通过IF判断语句,可以选择性地创建需要的实例化对象;但这时,如果需要增加新的水果,如葡萄时;需要改动两个地方:不仅需要新建一个葡萄的类,还需要在工厂类中添加判断和实例化语句。为了降低程序的耦合,这时需要用到反射的机制来动态的创建对象。
继续改进Factory类:
//工厂类,用生产对象 public class Factory { // 根据类型来创建对象 public FruitInterface getColour(String key) { FruitInterface f = null;// 定义接口对象,同过子类实例化 if ("Apple".equals(key)) { f = new Apple();// 通过Apple类实例化接口 } else if ("Orange".equals(key)) { f = new Orange();// 通过Orange类实例化接口 } return f; } // 通过反射,根据类的名称来生产对象 public FruitInterface getColourByClass(String className) throws Exception { FruitInterface fruit = (FruitInterface) Class.forName(className) .newInstance(); return fruit; } }
//客户端程序 public class FruitTest { public static void main(String[] args) throws Exception { //(1)普通设计模式,客户端需要显式的实现化对象 // FruitInterface f = new Apple(); // f.Colour(); //(2)工厂设计模式,客户端仅需要改变输入参数 //Factory factory = new Factory(); // FruitInterface colour = factory.getColour("Apple"); // colour.Colour(); //(3)通过反射的工厂设计模式,客户端仅需要改变输入参数 Factory factory = new Factory(); FruitInterface colour = factory.getColourByClass("com.fruit.Apple"); colour.Colour(); } }通过反射的工厂设计模式,当有新增加的类时,如增加葡萄这种水果,这时只需要新建一个子类Grape,并实现接口FruitInterface的方法Colour(),客户端仅需要改变输入参数(更改参数com.fruit.Apple即可),而Factory类不需要修改任何代码。
PS:通过反射的方式创建对象,性能会要稍微低些,通常情况下,没有必要使用反射来创建对象,只有当程序需要动态创建某个类的对象时才考虑使用反射。
四、升级改进:
通过反射的工厂设计模式已经可以大大的降低程序的耦合,但这时客户端输入参数时,需要输入整个完整的全限定类名(即完整的包名+类名),如果需要多个实例对象,这时客户端需要进行多次的更改参数;解决的方法是,把需要配置的参数以键值对象(Key-Value)的形式保存在属性文件中。而客户端只需要知道Key值就可以调用。
新建属性文件type.properties,其以key-value的形式保存输入参数和包名的对应关系
Apple=com.fruit.Apple Orange=com.fruit.Orange Grape=com.fruit.Grape有了属性文件,就需要获取和解释该属性文件的类PropertiesReader
//properties文件的读取工具 public class PropertiesReader { public Map<String, String> getProperties() { Properties props = new Properties(); Map<String, String> map = new HashMap<String, String>(); try { InputStream in = getClass().getResourceAsStream("type.properties"); props.load(in); Enumeration en = props.propertyNames(); while (en.hasMoreElements()) { String key = (String) en.nextElement(); String property = props.getProperty(key); map.put(key, property); // System.out.println(key + " " + property); } } catch (Exception e) { e.printStackTrace(); } return map; } }在工厂类Factory中,新增加一个方法getColourByClassKey,获取属性文件,并根据value值来生产对象:
//通过获取属性文件,根据value值来生产对象 public FruitInterface getColourByClassKey(String key) throws Exception { Map<String, String> map = new PropertiesReader().getProperties(); FruitInterface fruit = (FruitInterface) Class.forName(map.get(key)) .newInstance(); return fruit; }这时客户端只需要传入一个key值即可:
// (4)传入Key值,获取属性文件 FruitInterface colour = factory.getColourByClassKey("Apple"); colour.Colour();这种升级后的工厂设计模式,把需要的映射的关系都保存到属性文件中,客户端只需要知道属性文件中key值,就可以实现功能;维护时,只需要修改属性文件,把key值告诉客户端使用者即可。
相关文章推荐
- Java反射(二):反射的使用
- 创建线程的两种方式
- Java---设计模式(工厂方法)
- Java反射(一):获取类的反射
- myEclipse Socket编程半双工练习问题
- Java生成动态GIF图片
- 服务器用map来接收数据
- java反射机制
- JAVA中获取工程路径的方法
- JAVA对象数组的初始化
- java继承
- Spring Boot / Spring MVC 入门实践 (二) :MVC与Spring MVC简介
- 数值的整数次方
- java项目中的路径
- java泛型中<?>和<T>有什么区别?
- java文件操作
- eclipse启动不了
- 码神-day10-java
- Java的设计思想之工厂的实现
- 取出一个字符串中字母出现的次数。如:字符串:"abcde%^kka27qoq" ,输出格式为: a(2)b(1)k(2)...