組合模式,英文名稱是: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