编写工厂类和配置文件

为了知足“开闭原则”,大部分设计模式都引入了抽象层,如工厂方法模式、抽象工厂模式、适配器模式、桥接模式、命令模式、策略模式等等。客户端代码针对抽象层编程,而在程序运行的时候再指定其子类,根据“里氏代换原则”和面向对象的多态性,子类对象在运行时将覆盖父类对象。若是须要对系统进行扩展或修改,只需修改子类类名便可。在具体实现时,经过引入配置文件可使得用户在不修改任何客户端代码的前提下增长或替换子类,其基本实现过程以下:spring

(1)客户端针对抽象层编程,客户端代码中不能出现任何具体类类名,即客户端不直接实例化对象;
(2)引入纯文本格式的配置文件,一般是XML文件,将具体类类名存储在配置文件中;
(3)经过DOM(Document Object Model,文档对象模型)、SAX(Simple API for XML)等XML解析技术获取存储在配置文件中的类名;
(4)在客户端代码中经过反射(Reflection)机制根据类名建立对象,用反射所建立的对象替换父类对象的引用,程序运行时,将调用子类方法来实现业务功能;
(5)若是须要扩展功能,只需增长一个新的子类继承抽象父类,再修改配置文件,从新运行程序便可;若是须要替换功能,只需用另外一个子类类名替换存储在配置文件中的原有子类类名便可。不管是扩展仍是替换都无须修改既有类库和客户端源代码,彻底符合开闭原则。
编程

新建一个对象来获取配置属性:设计模式

package com.atomview.signalgateway.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * Created on 2018/10/9. */ public class StreamServerProperties { @Value("#{propertiesReader['state']}") private String m_ConnectState; @Value("#{propertiesReader['server.ip']}") private String m_StreamserverIp; @Value("#{propertiesReader['server.port']}") private String m_StreamserverPort; public String getConnectState() { return m_ConnectState; } public String getStreamserverIp() { return m_StreamserverIp; } public String getStreamserverPort() { return m_StreamserverPort; } }

这里面定义了5个IImageSelect接口的子类,经过定义好的泛型ImageSelectClientMode来决定实例化哪一个子类,如今遇到这么一个问题,若是添加到第6个子类的话,那就必需要更改ImageSelectFactory类以及枚举ImageSelectClientMode,虽不说影响不影响什么开闭设计原则,可是有个状况你可成想到,你这个类要打包发布给别人的话,别人在没有源码的状况下如何扩展呢?这里就须要咱们动态的经过配置文件来加载实现类了。atom

经过读取本地的.properties文件来获取咱们须要实例化的类,而后经过反射来生成对象,这样当你把发布出去的时候,使用者只用更改配置文件就可让工厂去实例化本身后来才写的实现类,咱们看看实现方式:spa

经过读取本地的.properties文件来获取咱们须要实例化的类,而后经过反射来生成对象,这样当你把发布出去的时候,使用者只用更改配置文件就可让工厂去实例化本身后来才写的实现类,咱们看看实现方式:设计

public static class ImageSelectFactory { public static IImageSelect createIImageSelect(String type) { IImageSelect mIImageSelect; //实例化Properties对象,用于读取.properties Properties properties = new Properties(); InputStream is = null; try { is = ImageSelectClient.class.getResourceAsStream("ImageSelectClient.properties"); //装载ImageSelectClient.properties文件 properties.load(is); } catch (Exception e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } try { //根据key获取value,value即为将要实例化的类 Class<?> aClass = Class.forName(properties.getProperty(type)); //使用反射进行实例化 mIImageSelect = (IImageSelect) aClass.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return mIImageSelect; }

咱们就能够随便实现子类,而后在.properties文件中添加对应的包路径,而后经过ImageSelectFactory就能够进行实例化了。3d

相关文章
相关标签/搜索