裝飾者模式(Decorator Pattern)是指在不改變原有對象的基礎之上,將功能附加到對象上,提供了比繼承更有彈性的替代方案(擴展原有對象的功能)微信
屬於結構型模式ide
適用場景: 1 用於擴展一個類的功能或給一個類添加附加職責0this
2 動態的給一個對象添加功能,這些功能能夠再動態的撤銷spa
裝飾者模式 | 適配器模式 | |
形式 | 是一種很是特別的適配器模式 | 沒有層級關係,裝飾器模式有層級關係 |
定義 | 裝飾者和被裝飾者都實現同一個接口,主要目的是爲了擴展以後依舊保留OOP關係設計 |
適配器和被適配者沒有必然的聯繫,一般是採用繼承或代理的形式進行包裝 |
關係 | 知足is-a的關係 | 知足has-a的關係 |
功能 | 注重覆蓋、擴展 | 注重兼容、轉換 |
設計 | 前置考慮 | 後置考慮 |
public abstract class Battercake { protected abstract String getMsg(); protected abstract int getPrice(); }
public class BaseBattercake extends Battercake { @Override protected String getMsg(){ return "煎餅"; } @Override public int getPrice(){ return 5; } }
public abstract class BattercakeDecorator extends Battercake { /** * 靜態代理,委派 */ private Battercake battercake; public BattercakeDecorator(Battercake battercake) { this.battercake = battercake; } protected abstract void doSomething(); @Override protected String getMsg() { return this.battercake.getMsg(); } @Override protected int getPrice() { return this.battercake.getPrice(); } }
public class EggDecorator extends BattercakeDecorator { public EggDecorator(Battercake battercake) { super(battercake); } @Override protected void doSomething() { } @Override protected String getMsg() { return super.getMsg() + "+1個雞蛋"; } @Override protected int getPrice() { return super.getPrice() + 1; } }
public class SausageDecorator extends BattercakeDecorator { public SausageDecorator(Battercake battercake) { super(battercake); } @Override protected void doSomething() { } @Override protected String getMsg() { return super.getMsg() + "+1根香腸"; } @Override protected int getPrice() { return super.getPrice() + 2; } }
public static void main(String[] args) { Battercake battercake; //路邊攤買一個煎餅 battercake = new BaseBattercake(); //煎餅有點小,想再加一個雞蛋 battercake = new EggDecorator(battercake); //很餓,再加根香腸 battercake = new SausageDecorator(battercake); //跟靜態代理最大區別就是職責不一樣 //靜態代理不必定要知足is-a的關係 //靜態代理會作功能加強,同一個職責變得不同 //裝飾器更多考慮是擴展 System.out.println(battercake.getMsg() + ",總價:" + battercake.getPrice()); }
優勢: 1 裝飾者是繼承的有力補充,比繼承靈活,不改變原有對象的狀況下動態地給一個對象擴展功能,即插即用3d
2 經過使用不一樣裝飾類以及這些裝飾類的排列組合,能夠實現不一樣效果代理
3 裝飾者徹底遵照開閉原則code
缺點:1 會出現更多的代碼,更多的類,增長程序複雜性對象
2 動態裝飾時,多層裝飾時會更復雜blog
public class Member { private String username; private String password; private String mid; private String 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 interface ISigninService { ResultMsg regist(String username, String password); /** * 登陸的方法 * @param username * @param password * @return */ ResultMsg login(String username, String password); }
public interface ISiginForThirdService extends ISigninService { /** * QQ登陸 * @param id * @return */ ResultMsg loginForQQ(String id); /** * 微信登陸 * @param id * @return */ ResultMsg loginForWechat(String id); /** * 記住登陸狀態後自動登陸 * @param token * @return */ ResultMsg loginForToken(String token); /** * 手機號登陸 * @param telphone * @param code * @return */ ResultMsg loginForTelphone(String telphone, String code); /** * 註冊後自動登陸 * @param username * @param passport * @return */ ResultMsg loginForRegist(String username, String passport); }
public class SiginForThirdService implements ISiginForThirdService { private ISigninService signinService; public SiginForThirdService(ISigninService signinService) { this.signinService = signinService; } @Override public ResultMsg regist(String username, String password) { return signinService.regist(username,password); } @Override public ResultMsg login(String username, String password) { return signinService.login(username,password); } @Override public ResultMsg loginForQQ(String id) { return null; } @Override public ResultMsg loginForWechat(String id) { return null; } @Override public ResultMsg loginForToken(String token) { return null; } @Override public ResultMsg loginForTelphone(String telphone, String code) { return null; } @Override public ResultMsg loginForRegist(String username, String passport) { return null; } }
public static void main(String[] args) { //知足一個is-a ISiginForThirdService siginForThirdService = new SiginForThirdService(new SigninService()); siginForThirdService.loginForQQ("Decorator"); }
源碼中運用裝飾器模式:
HttpHeadResponseDecorator繼承的父類 ServerHttpResponseDecorator