溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解Java設(shè)計模式的裝飾模式

發(fā)布時間:2021-11-08 10:39:43 來源:億速云 閱讀:147 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“如何理解Java設(shè)計模式的裝飾模式”,在日常操作中,相信很多人在如何理解Java設(shè)計模式的裝飾模式問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解Java設(shè)計模式的裝飾模式”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    一、前言

    裝飾模式實際上是一直提倡的組合代替繼承的實踐方式,個人認為要理解裝飾者模式首先需要理解為什么需要組合代替繼承,繼承又是為什么讓人深惡痛絕.

    為什么建議使用組合代替繼承?

    面向?qū)ο蟮奶匦杂欣^承與封裝,但兩者卻又有一點矛盾,繼承意味子類依賴了父類中的實現(xiàn),一旦父類中改變實現(xiàn)則會對子類造成影響,這是打破了封裝性的一種表現(xiàn). 而組合就是巧用封裝性來實現(xiàn)繼承功能的代碼復用.

    二、什么是裝飾模式

    1.定義:

    裝飾器模式又名包裝(Wrapper)模式。裝飾器模式以對客戶端透明的方式拓展對象的功能,是繼承關(guān)系的一種替代方案。

    2.意圖

    動態(tài)地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。

    3.別名

    包裝器Wrapper

    4.動機

    有時我們希望給某個對象而不是整個類添加一些功能。例如,一個圖形用戶界面工具箱允許你對任意一個用戶界面組件添加一些組件,例如邊框,或是一些行為,例如窗口滾動等。

    5.作用

    在不修改原有的接口的情況下,讓類表現(xiàn)的更好。

    6.問題

    自然是繼承有一些問題

    繼承會導致超類和子類之間存在強耦合性,當超類改變時,子類也會隨之改變;

    超類的內(nèi)部細節(jié)對于子類是可見的,繼承常常被認為破壞了封裝性;

    三、裝飾模式的結(jié)構(gòu)

    如何理解Java設(shè)計模式的裝飾模式

    在裝飾器模式中的角色有:

    • 抽象構(gòu)件(Component)角色:給出一個抽象接口,已規(guī)范準備接收附加責任的對象。

    • 具體構(gòu)件(ConcreteComponent)角色:定義一個將要接收附加責任的類

    • 裝飾(Decorator)角色:持有一個構(gòu)件(Component)對象的實例,并定義一個與抽象構(gòu)件接口一致的接口。

    • 具體裝飾(ConcreteDecorator)角色:負責給構(gòu)件對象“貼上”附加的責任。

    四、裝飾模式的使用場景

    1.需要擴展一個類的功能或給一個類增加附加責任。

    2.需要動態(tài)地給一個對象增加功能,這些功能可以再動態(tài)地撤銷。

    3.需要增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能

    五、裝飾模式的優(yōu)缺點

    優(yōu)點:

    1.裝飾這模式和繼承的目的都是擴展對象的功能,但裝飾者模式比繼承更靈活

    2.通過使用不同的具體裝飾類以及這些類的排列組合,設(shè)計師可以創(chuàng)造出很多不同行為的組合

    3.裝飾者模式有很好地可擴展性

    缺點:

    裝飾者模式會導致設(shè)計中出現(xiàn)許多小對象,如果過度使用,會讓程序變的更復雜。并且更多的對象會是的差錯變得困難,特別是這些對象看上去都很像。

    六、裝飾模式的實現(xiàn)

    /// <summary>
        /// 手機抽象類,即裝飾者模式中的抽象組件類
        /// </summary>
        public abstract class Phone
        {
            public abstract void Print();
        }
         /// <summary>
        /// 蘋果手機,即裝飾著模式中的具體組件類
        /// </summary>
        public class ApplePhone:Phone
        {
            /// <summary>
            /// 重寫基類方法
            /// </summary>
            public override void Print()
            {
                Console.WriteLine("開始執(zhí)行具體的對象——蘋果手機");
            }
        }
         /// <summary>
        /// 裝飾抽象類,要讓裝飾完全取代抽象組件,所以必須繼承自Photo
        /// </summary>
        public abstract class Decorator:Phone
        {
            private Phone phone;
             public Decorator(Phone p)
            {
                this.phone = p;
            }
             public override void Print()
            {
                if (phone != null)
                {
                    phone.Print();
                }
            }
        }
         /// <summary>
        /// 貼膜,即具體裝飾者
        /// </summary>
        public class Sticker : Decorator
        {
            public Sticker(Phone p)
                : base(p)
            { 
            }
             public override void Print()
            {
                base.Print();
                 // 添加新的行為
                AddSticker();      
            }
             /// <summary>
            /// 新的行為方法
            /// </summary>
            public void AddSticker()
            {
                Console.WriteLine("現(xiàn)在蘋果手機有貼膜了");
            }
        }
         /// <summary>
        /// 手機掛件
        /// </summary>
        public class Accessories : Decorator
        {
            public Accessories(Phone p)
                : base(p)
            {
            }
             public override void Print()
            {
                base.Print();
                 // 添加新的行為
                AddAccessories();          
            }
             /// <summary>
            /// 新的行為方法
            /// </summary>
            public void AddAccessories()
            {
                Console.WriteLine("現(xiàn)在蘋果手機有漂亮的掛件了");
            }
        }

    客戶端代碼

    class Customer
        {
            static void Main(string[] args)
            {
                // 我買了個蘋果手機
                Phone phone = new ApplePhone();
                 // 現(xiàn)在想貼膜了
                Decorator applePhoneWithSticker = new Sticker(phone);
                // 擴展貼膜行為
                applePhoneWithSticker.Print();
                Console.WriteLine("----------------------\n");
                 // 現(xiàn)在我想有掛件了
                Decorator applePhoneWithAccessories = new Accessories(phone);
                // 擴展手機掛件行為
                applePhoneWithAccessories.Print();
                Console.WriteLine("----------------------\n");
                 // 現(xiàn)在我同時有貼膜和手機掛件了
                Sticker sticker = new Sticker(phone);
                Accessories applePhoneWithAccessoriesAndSticker = new Accessories(sticker);
                applePhoneWithAccessoriesAndSticker.Print();
                Console.ReadLine();
            }

    從上面的客戶端代碼可以看出,客戶端可以動態(tài)地將手機配件增加到手機上,如果需要添加手機外殼時,此時只需要添加一個繼承Decorator的手機外殼類,從而,裝飾模式擴展性也非常好。

    七、裝飾模式的.NET應用

    在.NET 類庫中也有裝飾者模式的實現(xiàn),該類就是System.IO.Stream

    MemoryStream memoryStream = new MemoryStream(new byte[] {95,96,97,98,99});
                 // 擴展緩沖的功能
                BufferedStream buffStream = new BufferedStream(memoryStream);
                 // 添加加密的功能
                CryptoStream cryptoStream = new CryptoStream(memoryStream,new AesManaged().CreateEncryptor(),CryptoStreamMode.Write);
                // 添加壓縮功能
                GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Compress, true);

    到此,關(guān)于“如何理解Java設(shè)計模式的裝飾模式”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI