前言 組合模式,英文名稱是:Composite Pattern。當我們談到這個模式的時候,有一個物件和這個模式很像,也符合這個模式要表達的意思,那就是“俄羅斯套娃”。“俄羅斯套娃”就是大的瓷器娃娃裡面裝著一個小的瓷器娃娃,小的瓷器娃娃裡面再裝著更小的瓷器娃娃,直到最後一個不能再裝更小的瓷器娃娃的那個 ...
前言
組合模式,英文名稱是:Composite Pattern
。當我們談到這個模式的時候,有一個物件和這個模式很像,也符合這個模式要表達的意思,那就是“俄羅斯套娃”。“俄羅斯套娃”就是大的瓷器娃娃裡面裝著一個小的瓷器娃娃,小的瓷器娃娃裡面再裝著更小的瓷器娃娃,直到最後一個不能再裝更小的瓷器娃娃的那個瓷器娃娃為止。在我們的操作系統中有文件夾的概念,文件夾可以包含文件夾,可以嵌套多層,最裡面包含的是文件,這個概念和“俄羅斯套娃”很像。
組合模式的定義
客戶代碼過多地依賴於對象容器複雜的內部實現結構,對象容器內部實現結構的變化將引起客戶代碼的頻繁變化,帶來了代碼的維護性、擴展性等方面的弊端。組合設計模式就是將對象組合成樹形結構以表示“部分-整體”的層次結構。Composite使得用戶對單個對象和組合對象的使用具有一致性。
組合模式的組成
-
抽象構件角色(Component):這是個抽象角色,它給參加組合的對象定義出了公共的介面及預設行為,可以用來管理所有的子對象。在安全式的組合模式里,構件角色並不定義出管理子對象的方法,這一定義由樹枝結構對象給出。
-
樹葉構件角色(Leaf):樹葉對象是沒有下級子對象的對象,定義出參加組合的原始對象的行為。(原始對象的行為可以理解為沒有容器對象管理子對象的方法,或者 【原始對象行為】+【管理子對象的行為(Add,Remove等)】=面對客戶代碼的介面行為集合)
-
樹枝構件角色(Composite):代表參加組合的有下級子對象的對象,樹枝對象給出所有管理子對象的方法實現,如Add、Remove等。
組合模式的代碼實現
組合模式有兩種實現方式,一種是:透明式的組合模式,另外一種是:安全式的組合模式。
所謂透明式是指“抽象構件角色”定義的介面行為集合包含兩個部分,一部分是葉子對象本身所包含的行為(比如Operation),另外一部分是容器對象本身所包含的管理子對象的行為(Add,Remove)。這個抽象構件必須同時包含這兩類對象所有的行為,客戶端代碼才會透明的使用,無論調用容器對象還是葉子對象,介面方法都是一樣的,這就是透明。
所謂安全式是指“抽象構件角色”只定義葉子對象的方法,確切的說這個抽象構件只定義兩類對象共有的行為,然後容器對象的方法定義在“樹枝構件角色”上,這樣葉子對象有葉子對象的方法,容器對象有容器對象的方法,這樣責任很明確,當然調用肯定不會拋出異常了。
大家可以根據自己的情況自行選擇是實現為“透明式”還是“安全式”的,以下我們會針對這兩種情況都有實現,具體實現如下:
透明式
代碼定義
/// <summary>
/// Transparent 透明式實現
/// </summary>
public class Transparent
{
/// <summary>
/// 該抽象類就是文件夾抽象介面的定義,該類型就相當於是抽象構件Component類型
/// </summary>
public abstract class Folder
{
//增加文件夾或文件
public abstract void Add(Folder folder);
//刪除文件夾或者文件
public abstract void Remove(Folder folder);
//打開文件或者文件夾--該操作相當於Component類型的Operation方法
public abstract void Open();
}
/// <summary>
/// 該Word文檔類就是葉子構件的定義,該類型就相當於是Leaf類型,不能在包含子對象
/// </summary>
public sealed class Word : Folder
{
//增加文件夾或文件
public override void Add(Folder folder)
{
throw new Exception("Word文檔不具有該功能");
}
//刪除文件夾或者文件
public override void Remove(Folder folder)
{
throw new Exception("Word文檔不具有該功能");
}
//打開文件--該操作相當於Component類型的Operation方法
public override void Open()
{
Console.WriteLine("打開Word文檔,開始進行編輯");
}
}
/// <summary>
/// SonFolder類型就是樹枝構件,由於我們使用的是“透明式”,所以Add,Remove都是從Folder類型繼承下來的
/// </summary>
public class SonFolder : Folder
{
//增加文件夾或文件
public override void Add(Folder folder)
{
Console.WriteLine("文件或者文件夾已經增加成功");
}
//刪除文件夾或者文件
public override void Remove(Folder folder)
{
Console.WriteLine("文件或者文件夾已經刪除成功");
}
//打開文件夾--該操作相當於Component類型的Operation方法
public override void Open()
{
Console.WriteLine("已經打開當前文件夾");
}
}
}
調用實現
public void RunTest()
{
//Folder myword = new Word();
//myword.Open();//打開文件,處理文件
//myword.Add(new SonFolder());//拋出異常
//myword.Remove(new SonFolder());//拋出異常
Folder myfolder = new SonFolder();
myfolder.Open();//打開文件夾
myfolder.Add(new SonFolder());//成功增加文件或者文件夾
myfolder.Remove(new SonFolder());//成功刪除文件或者文件夾
Console.Read();
}
安全式
代碼定義
/// <summary>
/// Secure 安全式實現
/// </summary>
public class Secure
{
/// <summary>
/// 該抽象類就是文件夾抽象介面的定義,該類型就相當於是抽象構件Component類型
/// </summary>
public abstract class Folder //該類型少了容器對象管理子對象的方法的定義,換了地方,在樹枝構件也就是SonFolder類型
{
//打開文件或者文件夾--該操作相當於Component類型的Operation方法
public abstract void Open();
}
/// <summary>
/// 該Word文檔類就是葉子構件的定義,該類型就相當於是Leaf類型,不能在包含子對象
/// </summary>
public sealed class Word : Folder //這類型現在很乾凈
{
//打開文件---該操作相當於Component類型的Operation方法
public override void Open()
{
Console.WriteLine("打開Word文檔,開始進行編輯");
}
}
/// <summary>
/// SonFolder類型就是樹枝構件,現在由於我們使用的是“安全式”,所以Add,Remove都是從此處開始定義的
/// </summary>
public abstract class SonFolder : Folder //這裡可以是抽象介面,可以自己根據自己的情況而定
{
//增加文件夾或文件
public abstract void Add(Folder folder);
//刪除文件夾或者文件
public abstract void Remove(Folder folder);
//打開文件夾--該操作相當於Component類型的Operation方法
public override void Open()
{
Console.WriteLine("已經打開當前文件夾");
}
}
/// <summary>
/// NextFolder類型就是樹枝構件的實現類
/// </summary>
public sealed class NextFolder : SonFolder
{
//增加文件夾或文件
public override void Add(Folder folder)
{
Console.WriteLine("文件或者文件夾已經增加成功");
}
//刪除文件夾或者文件
public override void Remove(Folder folder)
{
Console.WriteLine("文件或者文件夾已經刪除成功");
}
//打開文件夾--該操作相當於Component類型的Operation方法
public override void Open()
{
Console.WriteLine("已經打開當前文件夾");
}
}
}
調用實現
public void RunTest()
{
//這是安全的組合模式
Folder myword = new Word();
myword.Open();//打開文件,處理文件
Folder myfolder = new NextFolder();
myfolder.Open();//打開文件夾
//此處要是用增加和刪除功能,需要轉型的操作,否則不能使用
((SonFolder)myfolder).Add(new NextFolder());//成功增加文件或者文件夾
((SonFolder)myfolder).Remove(new NextFolder());//成功刪除文件或者文件夾
}
組合模式的優缺點
優點
-
組合模式使得客戶端代碼可以一致地處理對象和對象容器,無需關心處理的是單個對象,還是組合的對象容器。
-
將”客戶代碼與複雜的對象容器結構“解耦。
-
可以更容易地往組合對象中加入新的構件。
缺點
- 使得設計更加複雜。客戶端需要花更多時間理清類之間的層次關係。
本文來自博客園,作者:碼農阿亮,轉載請註明原文鏈接:https://www.cnblogs.com/wml-it/p/17693267.html
技術的發展日新月異,隨著時間推移,無法保證本博客所有內容的正確性。如有誤導,請大家見諒,歡迎評論區指正!
開源庫地址,歡迎點亮:
GitHub:https://github.com/ITMingliang
Gitee: https://gitee.com/mingliang_it
GitLab: https://gitlab.com/ITMingliang
建群聲明: 本著技術在於分享,方便大家交流學習的初心,特此建立【編程內功修煉交流群】,為大家答疑解惑。熱烈歡迎各位愛交流學習的程式員進群,也希望進群的大佬能不吝分享自己遇到的技術問題和學習心得!進群方式:掃碼關註公眾號,後臺回覆【進群】。