C#設計模式系列:裝飾模式(Decorator)


1. 裝飾模式簡介

  裝飾模式動態地給一個對象添加額外的職責。例如一幅畫有沒有畫框都可以掛在牆上,畫就是被裝飾者。但是通常都是有畫框的。在掛在牆上之前,畫可以被蒙上玻璃,裝到框子里,所以在畫上加一層畫框,並把它們組合成一個整體——有框的畫。這樣隨着不斷有新的裝飾的加入,就給商品不斷地打上包裝,變成一個功能更讓人滿意的商品。這種不斷打包裝的過程就是裝飾。

1.1 定義

  裝飾模式提供了一種給類增加功能的方法。它通過動態地組合對象,可以給原有的類添加新的代碼,而無須修改現有代碼。因此引入bug或產生意外副作用的機會將大幅度減少。

1.2 使用頻率

   中等

2. 裝飾模式結構圖

2.1 結構圖

2.2 參與者

  裝飾模式參與者:

  ◊ Component:定義一個對象接口,可以給這些對象動態地添加職責

  ◊ ConcreteComponent:定義一個對象,可以給這個對象添加一些職責

  ◊ Decorator:維持一個指向Component的指針,並定義一個與Component接口一致的接口

  ◊ ConcreteDecorator:負責向ConcreteComponent添加功能

  在裝飾模式中,Decorator定義了一個裝飾接口類。因為Decorator與ConcreteComponent繼承同一個接口,所以繼承Decorator的類ConcreteDecorator可以使用ConcreteComponent的方法,再在ConcreteDecorator里面加入一些新的方法,也就是裝飾,就成為了一個包裝好的裝飾類。

3、裝飾模式結構實現

  Component.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.DecoratorPattern.Structural
{
    public abstract class Component
    {
        public abstract void Operation();
    }
}

  ConcreteComponent.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.DecoratorPattern.Structural
{
    public class ConcreteComponent : Component
    {
        public override void Operation()
        {
            Console.WriteLine("ConcreteComponent.Operation()");
        }
    }
}

  Decorator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.DecoratorPattern.Structural
{
    public abstract class Decorator : Component
    {
        protected Component component;

        public void SetComponent(Component component)
        {
            this.component = component;
        }
        
        public override void Operation()
        {
            if (component != null)
            {
                component.Operation();
            }
        }
    }
}

  ConcreteDecoratorA.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.DecoratorPattern.Structural
{
    public class ConcreteDecoratorA : Decorator
    {
        public override void Operation()
        {
            base.Operation();
            Console.WriteLine("ConcreteDecoratorA.Operation()");
        }
    }
}

  ConcreteDecoratorB.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.DecoratorPattern.Structural
{
    public class ConcreteDecoratorB : Decorator
    {
        public override void Operation()
        {
            base.Operation();
            AddedBehavior();
            Console.WriteLine("ConcreteDecoratorB.Operation()");
        }

        void AddedBehavior()
        {
        }
    }
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.DecoratorPattern.Structural;

namespace DesignPatterns.DecoratorPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create ConcreteComponent and two Decorators
            ConcreteComponent c = new ConcreteComponent();
            ConcreteDecoratorA d1 = new ConcreteDecoratorA();
            ConcreteDecoratorB d2 = new ConcreteDecoratorB();

            // Link decorators
            d1.SetComponent(c);
            d2.SetComponent(d1);

            d2.Operation();
        }
    }
}

  運行輸出:

ConcreteComponent.Operation()
ConcreteDecoratorA.Operation()
ConcreteDecoratorB.Operation()
請按任意鍵繼續. . .

4、裝飾模式應用分析

  裝飾模式適用情形:

  ◊ 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責

  ◊ 處理那些可以撤銷的職責

  裝飾模式的特點:

  ◊ 比靜態類更靈活。使用裝飾模式可以很容易地向對象添加職責的方式。可以用添加和分離的方法,對裝飾在運行時添加和刪除職責。相比之下,繼承機制要求為每個添加的職責創建一個新的子類。這會產生很多新的類,並會增加系統的復雜度。

  ◊ 使用裝飾模式可以很容易地重復添加一個特性,而兩次繼承特性類則極容易出錯。

  ◊ 為了避免處理頂層的類有太多的特征。裝飾模式下,你可以定義一個簡單的類,並用裝飾類給它逐漸地添加功能。這樣可以從簡單的部件組合出復雜的功能,具有低依賴性和地復雜性。

  ◊ 有許多小對象。采用裝飾模式進行系統設計往往會產生許多看上去類似的小對象,盡管對於了解這些系統的人來說,很容易進行定制,但是很難學習這些系統,排錯很惡化呢困難。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM