裝飾者模式 Decoration

1.什麼是裝飾者模式app

      動態給對象增長功能,從一個對象的外部來給對象添加功能,至關於改變了對象的外觀,比用繼承的方式更加的靈活。當使用裝飾後,從外部系統的角度看,就再也不是原來的那個對象了,而是使用一系列的裝飾器裝飾事後的對象。ide

2.結構工具

                                                                            

    角色:
    Component:組件對象的抽象接口,能夠給這些對象動態的增長職責/功能。
    ConcreteComponent:具體的組件的對象,實現組件對象的接口,是被裝飾器裝飾的原始對象,便可以給這個對象動態的添加職責。
    Decorator:全部裝飾器的抽象父類,實現了組件對象的接口,而且持有一個組件對象(被裝飾的對象)。
    ConcreteDecorator:具體的裝飾器,具體實現向裝飾對象添加功能。

3.示例測試

   下面咱們用裝飾者模式實現以下的功能:
    要求用戶輸入一段文字,好比 Hello Me,而後屏幕輸出幾個選項
    1 :加密
    2 :反轉字符串
    3:轉成大寫ui

    4:轉成小寫
    5:擴展或者剪裁到10個字符,不足部分用!補充
    6:用戶輸入 任意組合,好比 1,3 表示先執行1的邏輯,再執行3的邏輯
    根據用戶輸入的選擇,進行處理後,輸出結果this

 

//組件對象的接口
public interface ICompoment {

     String display(String str);
}
//具體的組件對象
public class DetailCompoment implements ICompoment {
    @Override
    public String display(String str) {
        System.out.println("原來內容:"+str);
        return str;
    }
}
//全部裝飾器的父類,實現了組件接口
public abstract class Decorator implements ICompoment{
      //持有了一個組件對象
      protected ICompoment compoment;

      public Decorator(ICompoment compoment) {
            this.compoment = compoment;
      }

      @Override
      public String display(String str) {
            return compoment.display(str);
      }
      //對組件對象進行裝飾的抽象方法
      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);
    }
}
//反轉 裝飾器
public class ReverseDecorator extends Decorator {

    public ReverseDecorator(ICompoment compoment) {
        super(compoment);
    }

    @Override
    public String display(String str) {
        String display = super.display(str);
        String transform = transform(display);
        return transform;
    }

    @Override
    public String transform(String str) {
        System.out.println("invoke ReverseDecorator....");
        StringBuilder sb = new StringBuilder(str);
        return sb.reverse().toString();
    }

}
//轉爲大寫的裝飾器
public class UpperDecorator extends Decorator {
    public UpperDecorator(ICompoment compoment) {
        super(compoment);
    }

    @Override
    public String display(String str) {
        String display = super.display(str);
        String transform = transform(display);
        return transform;
    }

    @Override
    public String transform(String str) {
        System.out.println("invoke UpperDecorator....");
        return str.toUpperCase();
    }
}
//轉爲小寫的裝飾器
public class LowerDecorator extends Decorator{
    public LowerDecorator(ICompoment compoment) {
        super(compoment);
    }

    @Override
    public String display(String str) {
        String display = super.display(str);
        String transform = transform(display);
        return transform;
    }

    @Override
    public String transform(String str) {
        System.out.println("invoke lowerDecorator....");
        return str.toLowerCase();
    }
}
//裁剪、擴充裝飾器
public class ExtendOrSplitDecorator extends Decorator {
    public ExtendOrSplitDecorator(ICompoment compoment) {
        super(compoment);
    }

    @Override
    public String display(String str) {
        String display = super.display(str);
        String transform = 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;
    }
}
//測試代碼
public static void main(String[] args) {
        //將輸入內容轉爲大寫,再反轉
        ReverseDecorator reverseDecorator = new ReverseDecorator(new UpperDecorator(new DetailCompoment()));
        String display = reverseDecorator.display("wo shi zhongguo ren.");
        System.out.println(display);

        //將輸入內容轉爲小寫,在裁剪或者擴展
        ExtendOrSplitDecorator decorator = new ExtendOrSplitDecorator(new LowerDecorator(new DetailCompoment()));
        String display1 = decorator.display("I Love");
        System.out.println(display1);

        //將輸入內容轉爲小寫,再反轉,而後加密
        EncodeDecorator decorator1 = new EncodeDecorator(new ReverseDecorator(new LowerDecorator(new DetailCompoment())));
        String display2 = decorator1.display("頂級機密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC");
        System.out.println(display2);
        System.out.println("++++++++++");
        //將輸入內容先反轉、再轉爲小寫,而後加密
        EncodeDecorator decorator2 = new EncodeDecorator(new LowerDecorator(new ReverseDecorator(new DetailCompoment())));
        String display3 = decorator2.display("頂級機密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC");
        System.out.println(display3);

        System.out.println("============");
        //對上面的加密內容,進行解密
        DecodeDecorator decodeDecorator = new DecodeDecorator(decorator1);
        String display4 = decodeDecorator.display("頂級機密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC");
        System.out.println(display4);
    }

控制檯輸出:加密

原來內容:wo shi zhongguo ren.
invoke UpperDecorator....
invoke ReverseDecorator....
.NER OUGGNOHZ IHS OW
原來內容:I Love
invoke lowerDecorator....
invoke ExtendOrSplitDecorator....
i love!!!!
原來內容:頂級機密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC
invoke lowerDecorator....
invoke ReverseDecorator....
invoke EncodeDecorator....
 URSP[晎硠宧蠭釵A⦆湎玁玬裌倖杍斄A榪SP帕PUXPサ宧杛細頗
++++++++++
原來內容:頂級機密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC
invoke ReverseDecorator....
invoke lowerDecorator....
invoke EncodeDecorator....
 URSP[晎硠宧蠭釵A⦆湎玁玬裌倖杍斄A榪SP帕PUXPサ宧杛細頗
============
原來內容:頂級機密:1941年12月 日本偷襲珍珠港! 銀行密碼是:1234ADC
invoke lowerDecorator....
invoke ReverseDecorator....
invoke EncodeDecorator....
invoke DecodeDecorator...
cda4321:是碼密行銀 !港珠珍襲偷本日 月21年1491:密機級頂spa

 

4.裝飾者模式在jdk中的應用I/Ocode

                                                 

    InputStream 至關於裝飾者模式的Component
    FileInputStream,ByteArrayInputStream,ObjectInputStream這些對象直接繼承了InputStream,至關於裝飾者模式中的ConcreteComponent
    FilterInputStream 繼承了InputStream,而且持有了一個InputStream ,至關於裝飾者模式中的Decorator
    BufferedInputStream,PushbackInputStream,LineNumberInputStream,DataInputStream繼承了FilterInputStream,至關於裝飾者模式中的ConcreteDecorator

 

 //這裏FileInputStream 至關於組件對象,BufferedInputStream這個裝飾器裝飾了FileInputStream對象
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("fileName")));
            byte[] buff = new byte[1024];
            bis.read(buff);
            System.out.println(new String(buff));

 

5.優勢、缺點,使用場合orm

  優勢:
    1.比繼承更靈活
    從爲對象添加功能的角度來看,裝飾者模式比繼承更爲靈活。繼承是靜態的,一旦繼承,全部的子類都有同樣的功能。裝飾者模式採用把功能分離到每一個裝飾器當中,
   經過對象組合的方式,在運行時動態的組合功能,被裝飾對象最終由哪些功能,是由運行時動態組合的功能決定的
    2.複用功能更容易
    裝飾模式把一系列複雜的功能分散到每一個裝飾器中,通常狀況下每一個裝飾器只實現一個功能,使得實現裝飾器變得簡單,有利於裝飾器功能的複用,能夠給一個對象添加
    多個裝飾器,也能夠把一個裝飾器裝飾多個對象,從而實現複用裝飾器的功能
    3.簡化高層定義
    裝飾者模式能夠經過組合裝飾器的方式,爲對象添加任意多的功能;所以在高層定義的時候,沒必要把全部的功能都定義處理,只須要定義最基本的就能夠了,在須要的時候能夠
    經過組合裝飾器的方式來完成所需的功能。

  缺點:會產生較多的細粒度的對象
  裝飾模式把一系列複雜的功能分散到每一個裝飾器中,通常狀況下每一個裝飾器只實現一個功能,這樣會產生不少細粒度的對象,而且功能越複雜,細粒度對象越多。

本質:動態組合
注意:裝飾者模式只是改變組件對象的外觀Facde,並無改變其內核

  使用場合:
    若是須要再不影響其餘對象的狀況下,以動態、透明的方式給對象增長職責,可使用裝飾者模式。
    若是不適合使用子類進行擴展的時候,能夠考慮使用裝飾者模式。裝飾者模式使用的是對象組合的方式。 不適合子類擴展:好比擴展功能須要的子類太多,形成子類數量呈爆炸性增加。
相關文章
相關標籤/搜索