這是我見(jiàn)過(guò)最通俗易懂的 裝飾者模式 講解了!
1.什么是裝飾者模式
動(dòng)態(tài)給對(duì)象增加功能,從一個(gè)對(duì)象的外部來(lái)給對(duì)象添加功能,相當(dāng)于改變了對(duì)象的外觀,比用繼承的方式更加的靈活。
當(dāng)使用裝飾后,從外部系統(tǒng)的角度看,就不再是原來(lái)的那個(gè)對(duì)象了,而是使用一系列的裝飾器裝飾過(guò)后的對(duì)象。
2.結(jié)構(gòu)
角色:
- Component:組件對(duì)象的抽象接口,可以給這些對(duì)象動(dòng)態(tài)的增加職責(zé)/功能。
 - ConcreteComponent:具體的組件的對(duì)象,實(shí)現(xiàn)組件對(duì)象的接口,是被裝飾器裝飾的原始對(duì)象,即可以給這個(gè)對(duì)象動(dòng)態(tài)的添加職責(zé)。
 - Decorator:所有裝飾器的抽象父類,實(shí)現(xiàn)了組件對(duì)象的接口,并且持有一個(gè)組件對(duì)象(被裝飾的對(duì)象)。
 - ConcreteDecorator:具體的裝飾器,具體實(shí)現(xiàn)向裝飾對(duì)象添加功能。
 
3.示例
下面我們用裝飾者模式實(shí)現(xiàn)如下的功能:更多:設(shè)計(jì)模式聚合
要求用戶輸入一段文字,比如 Hello Me,然后屏幕輸出幾個(gè)選項(xiàng)
- 加密
 - 反轉(zhuǎn)字符串
 - 轉(zhuǎn)成大寫(xiě)
 - 轉(zhuǎn)成小寫(xiě)
 - 擴(kuò)展或者剪裁到10個(gè)字符,不足部分用!補(bǔ)充
 - 用戶輸入 任意組合,比如 1,3 表示先執(zhí)行1的邏輯,再執(zhí)行3的邏輯
 - 根據(jù)用戶輸入的選擇,進(jìn)行處理后,輸出結(jié)果
 
- //組件對(duì)象的接口
 - public interface ICompoment {
 - String display(String str);
 - }
 
- //具體的組件對(duì)象
 - public class DetailCompoment implements ICompoment {
 - @Override
 - public String display(String str) {
 - System.out.println("原來(lái)內(nèi)容:"+str);
 - return str;
 - }
 - }
 
- //所有裝飾器的父類,實(shí)現(xiàn)了組件接口
 - public abstract class Decorator implements ICompoment{
 - //持有了一個(gè)組件對(duì)象
 - protected ICompoment compoment;
 - public Decorator(ICompoment compoment) {
 - this.compoment = compoment;
 - }
 - @Override
 - public String display(String str) {
 - return compoment.display(str);
 - }
 - //對(duì)組件對(duì)象進(jìn)行裝飾的抽象方法
 - public abstract String transform(String str);
 - }
 
- //加密、解密工具類
 - public class EnDecodeUtil {
 - private static final char password='a';
 - public static String encodeDecode(String str){
 - char[] chars = str.toCharArray();
 - for (int i = 0; i < chars.length; i++) {
 - chars[i] = (char) (chars[i] ^ password);
 - }
 - return new String(chars);
 - }
 - }
 
- //加密裝飾器
 - public class EncodeDecorator extends Decorator {
 - public EncodeDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - return transform(display);
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke EncodeDecorator....");
 - return EnDecodeUtil.encodeDecode(str);
 - }
 - }
 
- //解密裝飾器
 - public class DecodeDecorator extends Decorator {
 - public DecodeDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - return transform(display);
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke DecodeDecorator...");
 - return EnDecodeUtil.encodeDecode(str);
 - }
 - }
 
- //反轉(zhuǎn) 裝飾器
 - public class ReverseDecorator extends Decorator {
 - public ReverseDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - String transformtransform = transform(display);
 - return transform;
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke ReverseDecorator....");
 - StringBuilder sb = new StringBuilder(str);
 - return sb.reverse().toString();
 - }
 - }
 
- //轉(zhuǎn)為大寫(xiě)的裝飾器
 - public class UpperDecorator extends Decorator {
 - public UpperDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - String transformtransform = transform(display);
 - return transform;
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke UpperDecorator....");
 - return str.toUpperCase();
 - }
 - }
 
- //轉(zhuǎn)為大寫(xiě)的裝飾器
 - public class UpperDecorator extends Decorator {
 - public UpperDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - String transformtransform = transform(display);
 - return transform;
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke UpperDecorator....");
 - return str.toUpperCase();
 - }
 - }
 
- //轉(zhuǎn)為小寫(xiě)的裝飾器
 - public class LowerDecorator extends Decorator{
 - public LowerDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - String transformtransform = transform(display);
 - return transform;
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke lowerDecorator....");
 - return str.toLowerCase();
 - }
 - }
 
- //裁剪、擴(kuò)充裝飾器
 - public class ExtendOrSplitDecorator extends Decorator {
 - public ExtendOrSplitDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - String transformtransform = transform(display);
 - return transform;
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke ExtendOrSplitDecorator....");
 - if (str != null) {
 - if (str.length() > 10) {
 - return str.substring(0,10);
 - }else{
 - int repeatCount = 10 -str.length();
 - StringBuilder sb = new StringBuilder(str);
 - for (int i = 0; i < repeatCount; i++) {
 - sb.append("!");
 - }
 - return sb.toString();
 - }
 - }
 - return null;
 - }
 - }
 
- //裁剪、擴(kuò)充裝飾器
 - public class ExtendOrSplitDecorator extends Decorator {
 - public ExtendOrSplitDecorator(ICompoment compoment) {
 - super(compoment);
 - }
 - @Override
 - public String display(String str) {
 - String display = super.display(str);
 - String transformtransform = transform(display);
 - return transform;
 - }
 - @Override
 - public String transform(String str) {
 - System.out.println("invoke ExtendOrSplitDecorator....");
 - if (str != null) {
 - if (str.length() > 10) {
 - return str.substring(0,10);
 - }else{
 - int repeatCount = 10 -str.length();
 - StringBuilder sb = new StringBuilder(str);
 - for (int i = 0; i < repeatCount; i++) {
 - sb.append("!");
 - }
 - return sb.toString();
 - }
 - }
 - return null;
 - }
 - }
 
- //測(cè)試代碼
 - public static void main(String[] args) {
 - //將輸入內(nèi)容轉(zhuǎn)為大寫(xiě),再反轉(zhuǎn)
 - ReverseDecorator reverseDecorator = new ReverseDecorator(new UpperDecorator(new DetailCompoment()));
 - String display = reverseDecorator.display("wo shi zhongguo ren.");
 - System.out.println(display);
 - //將輸入內(nèi)容轉(zhuǎn)為小寫(xiě),在裁剪或者擴(kuò)展
 - ExtendOrSplitDecorator decorator = new ExtendOrSplitDecorator(new LowerDecorator(new DetailCompoment()));
 - String display1 = decorator.display("I Love");
 - System.out.println(display1);
 - //將輸入內(nèi)容轉(zhuǎn)為小寫(xiě),再反轉(zhuǎn),然后加密
 - EncodeDecorator decorator1 = new EncodeDecorator(new ReverseDecorator(new LowerDecorator(new DetailCompoment())));
 - String display2 = decorator1.display("頂級(jí)機(jī)密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC");
 - System.out.println(display2);
 - System.out.println("++++++++++");
 - //將輸入內(nèi)容先反轉(zhuǎn)、再轉(zhuǎn)為小寫(xiě),然后加密
 - EncodeDecorator decorator2 = new EncodeDecorator(new LowerDecorator(new ReverseDecorator(new DetailCompoment())));
 - String display3 = decorator2.display("頂級(jí)機(jī)密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC");
 - System.out.println(display3);
 - System.out.println("============");
 - //對(duì)上面的加密內(nèi)容,進(jìn)行解密
 - DecodeDecorator decodeDecorator = new DecodeDecorator(decorator1);
 - String display4 = decodeDecorator.display("頂級(jí)機(jī)密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC");
 - System.out.println(display4);
 - }
 
控制臺(tái)輸出:
- 原來(lái)內(nèi)容:wo shi zhongguo ren.
 - invoke UpperDecorator....
 - invoke ReverseDecorator....
 - .NER OUGGNOHZ IHS OW
 - 原來(lái)內(nèi)容:I Love
 - invoke lowerDecorator....
 - invoke ExtendOrSplitDecorator....
 - i love!!!!
 - 原來(lái)內(nèi)容:頂級(jí)機(jī)密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC
 - invoke lowerDecorator....
 - invoke ReverseDecorator....
 - invoke EncodeDecorator....
 - URSP[晎硠宧蠭釵A⦆湎玁玬裌倖?wèn)j斄A榪SP帕PUXPサ宧杛細(xì)頗
 - ++++++++++
 - 原來(lái)內(nèi)容:頂級(jí)機(jī)密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC
 - invoke ReverseDecorator....
 - invoke lowerDecorator....
 - invoke EncodeDecorator....
 - URSP[晎硠宧蠭釵A⦆湎玁玬裌倖?wèn)j斄A榪SP帕PUXPサ宧杛細(xì)頗
 - ============
 - 原來(lái)內(nèi)容:頂級(jí)機(jī)密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC
 - invoke lowerDecorator....
 - invoke ReverseDecorator....
 - invoke EncodeDecorator....
 - invoke DecodeDecorator...
 - cda4321:是碼密行銀 !港珠珍襲偷本日 月21年1491:密機(jī)級(jí)頂
 
4.裝飾者模式在jdk中的應(yīng)用I/O
- InputStream 相當(dāng)于裝飾者模式的Component
 - FileInputStream,ByteArrayInputStream,ObjectInputStream這些對(duì)象直接繼承了InputStream,相當(dāng)于裝飾者模式中的ConcreteComponent
 - FilterInputStream 繼承了InputStream,并且持有了一個(gè)InputStream ,相當(dāng)于裝飾者模式中的Decorator
 - BufferedInputStream,PushbackInputStream,LineNumberInputStream,DataInputStream繼承了FilterInputStream,相當(dāng)于裝飾者模式中的ConcreteDecorator
 
- //這里FileInputStream 相當(dāng)于組件對(duì)象,BufferedInputStream這個(gè)裝飾器裝飾了FileInputStream對(duì)象
 - BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("fileName")));
 - byte[] buff = new byte[1024];
 - bis.read(buff);
 - System.out.println(new String(buff));
 
5.優(yōu)點(diǎn)、缺點(diǎn),使用場(chǎng)合
優(yōu)點(diǎn):
1.比繼承更靈活
- 從為對(duì)象添加功能的角度來(lái)看,裝飾者模式比繼承更為靈活。繼承是靜態(tài)的,一旦繼承,所有的子類都有一樣的功能。裝飾者模式采用把功能分離到每個(gè)裝飾器當(dāng)中,
 - 通過(guò)對(duì)象組合的方式,在運(yùn)行時(shí)動(dòng)態(tài)的組合功能,被裝飾對(duì)象最終由哪些功能,是由運(yùn)行時(shí)動(dòng)態(tài)組合的功能決定的?! ?/li>
 
2.復(fù)用功能更容易
- 裝飾模式把一系列復(fù)雜的功能分散到每個(gè)裝飾器中,一般情況下每個(gè)裝飾器只實(shí)現(xiàn)一個(gè)功能,使得實(shí)現(xiàn)裝飾器變得簡(jiǎn)單,有利于裝飾器功能的復(fù)用,可以給一個(gè)對(duì)象添加
 - 多個(gè)裝飾器,也可以把一個(gè)裝飾器裝飾多個(gè)對(duì)象,從而實(shí)現(xiàn)復(fù)用裝飾器的功能。
 
3.簡(jiǎn)化高層定義
- 裝飾者模式可以通過(guò)組合裝飾器的方式,為對(duì)象添加任意多的功能;因此在高層定義的時(shí)候,不必把所有的功能都定義處理,只需要定義最基本的就可以了,在需要的時(shí)候可以
 - 通過(guò)組合裝飾器的方式來(lái)完成所需的功能。
 
缺點(diǎn):會(huì)產(chǎn)生較多的細(xì)粒度的對(duì)象
- 裝飾模式把一系列復(fù)雜的功能分散到每個(gè)裝飾器中,一般情況下每個(gè)裝飾器只實(shí)現(xiàn)一個(gè)功能,這樣會(huì)產(chǎn)生很多細(xì)粒度的對(duì)象,并且功能越復(fù)雜,細(xì)粒度對(duì)象越多。
 
本質(zhì):動(dòng)態(tài)組合
注意:裝飾者模式只是改變組件對(duì)象的外觀Facde,并沒(méi)有改變其內(nèi)核
使用場(chǎng)合:
- 如果需要再不影響其他對(duì)象的情況下,以動(dòng)態(tài)、透明的方式給對(duì)象增加職責(zé),可以使用裝飾者模式。
 - 如果不適合使用子類進(jìn)行擴(kuò)展的時(shí)候,可以考慮使用裝飾者模式。裝飾者模式使用的是對(duì)象組合的方式。
 - 不適合子類擴(kuò)展:比如擴(kuò)展功能需要的子類太多,造成子類數(shù)量呈爆炸性增長(zhǎng)。
 

















 
 
 














 
 
 
 