一 装饰模式的应用分析
1.1 InputStream的类结构图:
public interface Cache {
String getId();
void putObject(Object varl,Object var2);
Object getObject(Object var1);
Object removeObject(Object var1);
void clear();
int getSize();
ReadWriteLock getReadWriteLock();
}
1.2 Spring 中TransactionAwareCacheDecorator事务缓存
private final Cache targetCache;
/**
-
Create a new TransactionAwareCache for the given target Cache.
-
@param targetCache the target Cache to decorate
/
public TransactionAwareCacheDecorator(Cache targetCache) {
Assert.notNull(targetCache, “Target Cache must not be null”);
this.targetCache = targetCache;
}
/* -
Return the target Cache that this Cache should delegate to.
*/
public Cache getTargetCache() {
return this.targetCache;
}
TransactionAwareCacheDecorator 就是对Cache的一个包装。
1.3 MVC中的装饰者模式HttpHeadResponseDecorator类
public class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {public HttpHeadResponseDecorator(ServerHttpResponse delegate) {
super(delegate);
}
1.4
Mybatis 中的 处理缓存的设计
二 定义
装饰者模式是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有的对象的功能),属于结构型模式。装饰者模式在我们的生活中应用也是比较多的,比如,买车子选配置,卖电脑增加配置等等。给对象扩展一些额外的功能。
适用场景
1 用于扩展一个类的功能或者给一个类添加附加职责。
2、动态的给一个对象添加功能,这些功能在动态的撤销。
装饰者模式最本质的特征是将原有的类的附加功能抽离出来,简化原有类的逻辑。通过这样的案例,我们可以得出结论,其实抽象的装饰者是可有可无的,具体可以根据业务模型来进行选择。
装饰者模式的优缺点
优点:
1、装饰者是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用
2、通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同的效果
3、装饰者完全遵循开闭原则
缺点:
1、会出现更多的代码,更多的类,增加程序的复杂性
2、动态装饰时,多层装饰时会更加复杂。
三 代码实现
需求——用装饰模式实现登录功能 (实现第三方登录)
3.1准备
a 用户类
public class User {
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;
}
@Override
public String toString() {
return “User [username=” + username + “, password=” + password + “, mid=” + mid + “, info=” + info + “]”;
}
}
返回信息类
public class ResultMsg {
private int code;
private String msg;
private Object data;
public ResultMsg(int code, String msg, Object data) {
super();
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;
}
@Override
public String toString() {
return “ResultMsg [code=” + code + “, msg=” + msg + “, data=” + data + “]”;
}
}
3.2 登录基本实现
public interface loginService {
/**
* 注册接口
* @param name
* @param psw
* @return
*/
ResultMsg regist(String name, String psw);
/**
- 登录接口
- @param name
- @param psw
- @return
*/
ResultMsg login(String name, String psw);
}
登录实现类
public class loginServiceImpl implements loginService{
@Override
public ResultMsg regist(String name, String psw) {
// TODO Auto-generated method stub
return new ResultMsg(200, "注册成功", new User());
}
@Override
public ResultMsg login(String name, String psw) {
// TODO Auto-generated method stub
return null;
}
}
3.3 升级至第三方登录
public interface loginThirdService extends loginService{
//QQ登录
ResultMsg loginForQQ(String id);
//微信登录
ResultMsg loginForWeChat(String id);
//手机号登录
ResultMsg loginForPhone(String telephone,String code);
//token 登录
ResultMsg loginForToken(String id);
}
第三方登录实现类
public class loginForThirdServiceImpl implements loginThirdService{
private loginService loginService;
public loginForThirdServiceImpl(com.cy.decoractor.loginService loginService) {
super();
this.loginService = loginService;
}
@Override
public ResultMsg regist(String name, String psw) {
// TODO Auto-generated method stub
return loginService.regist(name, psw);
}
@Override
public ResultMsg login(String name, String psw) {
// TODO Auto-generated method stub
return loginService.login(name, psw);
}
@Override
public ResultMsg loginForQQ(String id) {
// TODO Auto-generated method stub
System.out.println("ID"+"的用户开始登录操作");
return new ResultMsg(200, "QQ登录成功", new User());
}
@Override
public ResultMsg loginForWeChat(String id) {
// TODO Auto-generated method stub
System.out.println("ID"+"的用户开始登录操作");
return new ResultMsg(200, "微信登录成功", new User());
}
@Override
public ResultMsg loginForPhone(String telephone, String code) {
System.out.println("ID"+"的用户开始登录操作");
return new ResultMsg(200, "手机登录成功", new User());
}
@Override
public ResultMsg loginForToken(String id) {
// TODO Auto-generated method stub
System.out.println("ID"+"的用户开始登录操作");
return new ResultMsg(200, "Token登录成功", new User());
}
}
客户端测试:
public static void main(String[] args) {
loginThirdService loginForThirdService = new loginForThirdServiceImpl(new loginServiceImpl());
ResultMsg resultMsg = loginForThirdService.loginForQQ("1231233");
System.out.println(resultMsg.getMsg());
}
运行结果
装饰者模式和适配器模式对比
装饰者和适配者都是包装模式,装饰者也是一种特殊的代理模式。
装饰者模式 适配器模式
定义 装饰者和被装饰者都实现同一个 接口,主要目的是为了扩展之后依旧保留OOP关系 适配器和被适配者没有必然的联系,通常采用继承或者代理的形式进行包装
形式 是一种非常特殊的适配器模式 没有层级关系,装饰者模式有层级关系
关系 满足 is-a 的关系 满足has -a的关系
功能 注重覆盖和扩展 注重兼容和转换
设计 前置考虑 后置考虑