设计模式之装饰者模式

前言

装饰着模式(Decorator Pattern),是在不改变原类文件的情况下,动态扩展一个对象的功能。它是通过创建一个包装对象,也就是用来包裹真实的对象。由装饰对象接受所有来自客户端的请求,并把这些请求转发给真实的对象,并且装饰对象可以在转发这些请求之前或之后增加一些附加功能。从而达到不用修改给定对象的结构就可以在外部增加附加功能的效果。在jdk中经典的使用案例就是io操作相关类,BufferedInputStream,FileInputStream等。

场景案例

Apache JSONObject中,根据key获取value时,如果指定的key在JSONObject对象中不存在的话,会报NullPointException。为了防止报错,在业务代码中,就会大量出现以下不够优雅的代码,而且是几乎所有业务代码解析参数的地方都会出现,这是代码中的坏味道,我们就可以采用装饰者模式进行解决。

JSONObject jsonObj = new JSONObject();
String param = jsonObj.contains("param")?jsonObj.getString("param"):"";

场景设计

类设计图(装饰者模式)

示例代码

JSONWrapper 包装类:
public class JSONWrapper {
private JSONObject realJsonObj = null;

public JSONWrapper(JSONObject jsonObj) {
if(jsonObj == null){
throw new IlegalAgurementException("jsonObj is null.");
}
this.realJsonObj = jsonObj;
}

//这里标准的是需要实现接口的
public String getString(String key){
// 在调用被装饰着对象之前,附加校验是否包含指定key的功能
if(realJsonObj.contains(key)){
return realJsonObj.getString(key);
}
return null;
}

public String getString(String key, String defaultValue){
String value = getString(key);
return value != null? value : defaultValue;
}

//getInteger(),getLong(),getObject(),getBoolean()等同上实现即可!

}

client 测试:
public class Client {
public static void main(String[] args) {
JSONObject jsonObj = new JSONObject();
jsonObj.put("key","value");
JSONWrapper wrapper = new JSONWrapper(jsonObj);
//哈哈哈...,妈妈,再也不用担心报空指针异常了
System.out.println(wrapper.getString("key1"));
}
}

软件设计原则

  1. 开闭原则

    对扩展开放,修改关闭;装饰着模式可以动态的对组件进行扩展,增添新的功能,完全是增量修改,对原有的软件功能结构不会产生任何的影响。

  2. 单一职责原则

    示例:BufferedInputStream buffIo = new BufferedInputStream(new FileInputStream(“filepath”));
    BufferedInputStream是对FileInputStream的装饰,在原有的FileInputStream文件IO读取的基础上增添了缓冲区的功能,避免频繁的读写磁盘IO带来的性能损耗。

    BufferedInputStream专注于buffer缓冲功能职责,FileInputStream专注于文件IO读写功能职责;两个类职责单一清晰,相互隔离且可以组合使用。程序的扩展性更强。