Decorator 装饰者模式,又叫包装器模式。为了某个实现类在不修改原始类的基础上,进行动态的覆盖或者增加方法该实现保持跟原有类的层级关系,装饰模式,实际是一种非常特殊的适配器模式。
应用场景:如java 中IO流的包装
//虽然DataInputStream 功能更加强大
//DataInputStream同样实现InputStream
InputStream in = null;
//Data将InputStream这个InputStream的引用进行一个包装,这样的形式就叫装饰器模式
FilterInputStream fis = new DataInputStream(in);
Demo
old包 即原来未进行装饰的类
public interface IsiginService {
/**
*注册方法
* @param username
* @param password
* @return
*/
public adapter.ResultMsg regist(String username, String password);
/**
* 登录方法
* @param username
* @param password
* @return
*/
public ResultMsg login(String username, String password);
}
public class Member {
private String username;
private String password;
private String mid;
private String info;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
public class ResultMsg {
private int code;
private String msg;
private Object data;
public ResultMsg(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
public class SiginService implements IsiginService{
/**
*注册方法
* @param username
* @param password
* @return
*/
public adapter.ResultMsg regist(String username, String password){
return new adapter.ResultMsg(200,"注册成功", new Member());
}
/**
* 登录方法
* @param username
* @param password
* @return
*/
public ResultMsg login(String username, String password){
return null;
}
}
upgrede 装饰类所在的包
public interface ISiginForThirdService extends IsiginService {
public ResultMsg loginForQQ(String openId);
public ResultMsg loginForWechat(String openId);
public ResultMsg loginForToken(String token);
public ResultMsg loginForTelphone(String telphone,String code);
public ResultMsg loginForRegist(String username,String password);
}
public class SiginForThirdService implements ISiginForThirdService {
private IsiginService service;
public SiginForThirdService(IsiginService service) {
this.service = service;
}
@Override
public ResultMsg regist(String username, String password) {
return service.regist(username,password);
}
@Override
public ResultMsg login(String username, String password) {
return service.login(username,password);
}
public ResultMsg loginForQQ(String openId){
ResultMsg loginMsg = this.login(openId, null);
return loginForRegist(openId,null);
}
public ResultMsg loginForWechat(String openId){
return null;
}
public ResultMsg loginForToken(String token){
//通过拿到token 信息再登录一次
return null;
}
public ResultMsg loginForTelphone(String telphone,String code){
return null;
}
public ResultMsg loginForRegist(String username,String password){
ResultMsg registMsg = this.regist(username, null);
return this.login(username, null);
}
}
public class SignTest {
public static void main(String[] args) {
//这样用的好处就是保留了原来的方法和逻辑,两个类去使用的话并不相互影响,对SiginService 做了个升级
//原来的功能依旧对外开放,依旧保留。新的功能同样的也可以用
ISiginForThirdService siginForThirdService = new SiginForThirdService(new SiginService());
}
}
装饰模式与适配器模式的对比
装饰器模式 | 适配器模式 |
是一种非常特别的适配器模式,要保留层级关系 | 可以不保留层级关系 |
装饰者和被装饰者都要实现同一个接口,主要目的是为了扩展,依旧保留OOP 的关系 | 适配者和被适配者没有必然的层级联系,通常采用代理或者继承的形式进行包装 |
满足并保留 is - a的关系 | 满足has - a 的关系 |
装饰器模式注重的覆盖、和扩展 | 注重的是兼容和转换 |
Spring 中用到的包装器模式在类名上有两种表现:一种是类名中含有 Wrapper,另一种是类名中含有 Decorator。基本上都是动态地给一个对象添加一些额外的职责。