天天看點

【愚公系列】2021年12月 二十三種設計模式(九)-裝飾者模式(Decorator Pattern)

文章目錄

前言

一、裝飾者模式(Decorator Pattern)

二、使用步驟

角色

示例

總結

優點

缺點

使用場景

設計模式(Design pattern)是一套被反複使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人了解、保證代碼可靠性。 毫無疑問,設計模式于己于他人于系統都是多赢的,設計模式使代碼編制真正工程化,設計模式是軟體工程的基石,如同大廈的一塊塊磚石一樣。項目中合理的運用設計模式可以完美的解決很多問題,每種模式在現在中都有相應的原理來與之對應,每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的核心解決方案,這也是它能被廣泛應用的原因。

提示:以下是本篇文章正文内容,下面案例可供參考

裝飾者模式屬于結構型模式,裝飾模式是在不必改變原類檔案和使用繼承的情況下,動态地擴充一個對象的功能。

裝飾者模式通過建立一個包裝對象(wrapper),也就是用裝飾來包裹真實的對象。

1、抽象構件(Component)

給出一個抽象接口,以規範準備接收附加責任的對象;

2、具體構件(Concrete Component)

定義一個将要接收附加責任的類;

3、抽象裝飾(Decorator)

持有一個構件(Component)對象的執行個體,并實作一個與抽象構件接口一緻的接口;

4、具體裝飾(Concrete Decorator)

負責給構件對象添加上附加的責任。

【愚公系列】2021年12月 二十三種設計模式(九)-裝飾者模式(Decorator Pattern)
命名空間DecoratorPattern中包含汽車Car類、瑪莎拉蒂Maserati類、法拉利Fabbrica類、酷汽車CoolCar類、汽車車貼Paster類和汽車遮陽擋Visor類。本示例通過使用裝飾者模式為汽車進行一次簡單的外觀裝飾。

public abstract class Car {

    public string Name { get; set; }

    public abstract void StartUp();

}      

汽車基類Car,充當抽象構件。

public class Fabbrica : Car {
 
    public Fabbrica() {
        Name = "Fabbrica";
    }
 
    public override void StartUp() {
        Console.WriteLine($"{Name} is starting!");
    }
 
}      

法拉利Fabbrica類,充當具體構件。

public class Maserati : Car {
 
    public Maserati() {
        Name = "Maserati";
    }
 
    public override void StartUp() {
        Console.WriteLine($"{Name} is starting!");
    }
 
}      

瑪莎拉蒂Maserati類,充當具體構件。

public abstract class CoolCar : Car {
 
    protected Car _car = null;
 
    public CoolCar(Car car) {
        _car = car;
    }
 
    public override void StartUp() {
        Console.WriteLine($"{_car.Name} is starting!");
    }
 
}      

酷汽車CoolCar類,充當抽象裝飾。

public class Paster : CoolCar {
 
    public Paster(Car car) : base(car) {
 
    }
 
    public override void StartUp() {
        SetPaster();
        base.StartUp();
    }
 
    private void SetPaster() {
        Console.WriteLine($"Set paster to {_car.Name}!");
    }
 
}      

汽車車貼Paster類,通過繼承CoolCar類,為對汽車進行裝飾提供了可能。

public class Visor : CoolCar {
 
    public Visor(Car car) : base(car) {
 
    }
 
    public override void StartUp() {
        SetVisor();
        base.StartUp();
    }
 
    private void SetVisor() {
        Console.WriteLine($"Set visor to {_car.Name}!");
    }
 
}      

汽車遮陽擋Visor 類,通過繼承CoolCar類,為對汽車進行裝飾提供了可能。

public class Program {

    private const string LINE_SPLIT = "-------------------------";

    private static Car _car = null;

    private static CoolCar _coolCar = null;

    public static void Main(string[] args) {
        _car = new Maserati();

        _coolCar = new Visor(_car);
        _coolCar.StartUp();
        Console.WriteLine(LINE_SPLIT);

        _car = new Fabbrica();

        _coolCar = new Paster(_car);
        _coolCar.StartUp();
        Console.WriteLine(LINE_SPLIT);

        Console.ReadKey();
    }

}      

以上是調用方的代碼,以下是這個案例的輸出結果:

Set visor to Maserati!
Maserati is starting!
-------------------------
Set paster to Fabbrica!
Fabbrica is starting!
-------------------------      

1、裝飾者模式與繼承關系的目的都是要擴充對象的功能,但是裝飾者模式可以提供比繼承更多的靈活性;

2、通過使用不同的具體裝飾類以及這些裝飾類的排列組合,開發者可以創造出很多不同行為的組合。

1、這種比繼承更加靈活機動的特性,也同時意味着更加多的複雜性;

2、裝飾模式會導緻設計中出現許多小類,如果過度使用,會使程式變得很複雜;

3、裝飾模式是針對抽象元件(Component)類型程式設計。但是,如果你要針對具體元件程式設計時,就應該重新思考你的應用架構,以及裝飾者是否合适。當然也可以改變Component接口,增加新的公開的行為,實作“半透明”的裝飾者模式。在實際項目中要做出最佳選擇。

1、需要擴充一個類的功能,或給一個類添加附加職責;

2、需要動态的給一個對象添加功能,這些功能可以再動态的撤銷;

3、需要增加由一些基本功能的排列組合而産生的非常大量的功能,進而使繼承關系變的不現實;

4、當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充,為支援每一種組合将産生大量的子類,使得子類數目呈爆炸式增長。另一種情況可能是因為類定義被隐藏,或類定義不能用于生成子類。

繼續閱讀