一. 組合模式
1. 背景
在現實生活中,存在很多“部分-整體”的關系,例如,大學中的部門與學院、總公司中的部門與分公司、學習用品中的書與書包、生活用品中的衣月艮與衣櫃以及廚房中的鍋碗瓢盆等。在軟體開發中也是這樣,例如,檔案系統中的檔案與檔案夾、窗體程式中的簡單控件與容器控件等。對這些簡單對象與複合對象的處理,如果用組合模式來實作會很友善。
2. 定義和特點
(1). 定義:有時又叫作部分-整體模式,它是一種将對象組合成樹狀的層次結構的模式,用來表示“部分-整體”的關系,使使用者對單個對象群組合對象具有一緻的通路性。
(2). 優點:
A. 組合模式使得用戶端代碼可以一緻地處理單個對象群組合對象,無須關心自己處理的是單個對象,還是組合對象,這簡化了用戶端代碼;
B. 更容易在組合體内加入新的對象,用戶端不會因為加入了新的對象而更改源代碼,滿足“開閉原則”;
(3). 缺點
A. 設計較複雜,用戶端需要花更多時間理清類之間的層次關系;
B. 不容易限制容器中的構件;
C. 不容易用繼承的方法來增加構件的新功能;
3. 具體實作
(1). 模式結構
可以自身嵌套結構。
(2). 使用場景
存儲上下級關系,CEO→技術主管→員工;CEO→銷售主管→員工。
(3). 代碼實操
上下級自身嵌套代碼:
/// <summary>
/// 員工類
/// </summary>
public class Employee
{
private string name;
private string dept;
private int salary;
//代表下級子類
private List<Employee> subordinates;
//構造函數
public Employee(string name, string dept, int sal)
{
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new List<Employee>();
}
public void add(Employee e)
{
subordinates.Add(e);
}
public void remove(Employee e)
{
subordinates.Remove(e);
}
public List<Employee> getSubordinates()
{
return subordinates;
}
public string toString()
{
return ("Employee :[ Name : " + name
+ ", dept : " + dept + ", salary :"
+ salary + " ]");
}
}
測試代碼:
{
// 1、樹形機構的場景,使用組合模式
Employee CEO = new Employee("張三", "CEO", 30000);
Employee headMarketing = new Employee("李四", "技術經理", 20000);
Employee headSales = new Employee("王五", "銷售經理", 20000);
Employee clerk1 = new Employee("趙六", "銷售", 10000);
Employee clerk2 = new Employee("錢七", "銷售", 10000);
Employee salesExecutive1 = new Employee("Tony", "技術", 10000);
Employee salesExecutive2 = new Employee("Mark", "技術", 10000);
CEO.add(headSales);
CEO.add(headMarketing);
headSales.add(clerk1);
headSales.add(clerk2);
headMarketing.add(salesExecutive1);
headMarketing.add(salesExecutive2);
//列印該組織的所有員工
Console.WriteLine(CEO.toString());
foreach (Employee headEmployee in CEO.getSubordinates())
{
Console.WriteLine(headEmployee.toString());
foreach (Employee employee in headEmployee.getSubordinates())
{
Console.WriteLine(employee.toString());
}
}
}
運作結果:
4. 适用場景分析
A. 在需要表示一個對象整體與部分的層次結構的場合。
B. 要求對使用者隐藏組合對象與單個對象的不同,使用者可以用統一的接口使用組合結構中的所有對象的場合。
更多C++背景開發技術點知識内容包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒體,音視訊開發,Linux核心,TCP/IP,協程,DPDK多個進階知識點。
C/C++背景開發架構師免費學習位址:C/C++Linux鏈嶅姟鍣ㄥ紑鍙�/鍚庡彴鏋舵瀯甯堛€愰浂澹版暀鑲層€�-瀛︿範瑙嗛鏁欑▼-鑵捐璇懼爞
【文章福利】另外還整理一些C++背景開發架構師 相關學習資料,面試題,教學視訊,以及學習路線圖,免費分享有需要的可以點選 「連結」 免費領取
二. 建築者模式
1. 背景
在軟體開發過程中有時需要建立一個複雜的對象,這個複雜對象通常由多個子部件按一定的步驟組合而成。例如,計算機是由 OPU、主機闆、記憶體、硬碟、顯示卡、機箱、顯示器、鍵盤、滑鼠等部件組裝而成的,采購員不可能自己去組裝計算機,而是将計算機的配置要求告訴計算機銷售公司,計算機銷售公司安排技術人員去組裝計算機,然後再交給要買計算機的采購員。
生活中這樣的例子很多,如遊戲中的不同角色,其性别、個性、能力、臉型、體型、服裝、發型等特性都有所差異;還有汽車中的方向盤、發動機、車架、輪胎等部件也多種多樣;每封電子郵件的發件人、收件人、主題、内容、附件等内容也各不相同。
以上所有這些産品都是由多個部件構成的,各個部件可以靈活選擇,但其建立步驟都大同小異。這類産品的建立無法用前面介紹的工廠模式描述,隻有建造者模式可以很好地描述該類産品的建立。
2. 定義和特點
(1). 定義
指将一個複雜對象的構造與它的表示分離,使同樣的建構過程可以建立不同的表示,這樣的設計模式被稱為建造者模式。它是将一個複雜的對象分解為多個簡單的對象,然後一步一步建構而成。它将變與不變相分離,即産品的組成部分是不變的,但每一部分是可以靈活選擇的。
(2). 優點
A. 各個具體的建造者互相獨立,有利于系統的擴充。
B. 用戶端不必知道産品内部組成的細節,便于控制細節風險。
(3). 缺點
A. 産品的組成部分必須相同,這限制了其使用範圍。
B. 如果産品的内部變化複雜,該模式會增加很多的建造者類。
(4). 與工廠方法模式的差別
建造者模式注重零部件的組裝過程,而工廠方模式更注重零部件的建立過程,但兩者可以結合使用。
3. 具體實作
(1). 模式結構
建造者(Builder)模式由産品、抽象建造者、具體建造者、指揮者等 4 個要素構成。
A. 産品角色(Product):它是包含多個組成部件的複雜對象,由具體建造者來建立其各個零部件。
B. 抽象建造者(Builder):它是一個包含建立産品各個子部件的抽象方法的接口,通常還包含一個傳回複雜産品的方法 getResult()。
C. 具體建造者(Concrete Builder):實作 Builder 接口,完成複雜産品的各個部件的具體建立方法。
D. 指揮者(Director):它調用建造者對象中的部件構造與裝配方法完成複雜對象的建立,在指揮者中不涉及具體産品的資訊。
PS:如果建立的産品種類隻有一種,隻需要一個具體建造者,這時可以省略掉抽象建造者,甚至可以省略掉指揮者角色。
結構圖如下:
(2). 使用場景
現在要建構自行車,包括核心元件frame、seat、tire,而每個元件可選的材料有多種,自行車的建構順序是固定的,比如按照這個順序:BuidFrame、BuildSeat、BuildTire。這個場景就可以使用建築者模式。
(3). 代碼實操
各種自行車材料代碼:
/// <summary>
/// 自行車架構
/// </summary>
public interface IFrame
{
void show();
}
/// <summary>
/// 自行車座椅
/// </summary>
public interface ISeat
{
void show();
}
/// <summary>
/// 自行車輪胎
/// </summary>
public interface ITire
{
void show();
}
/// <summary>
/// 合金自行車架構1
/// </summary>
public class AlloyFrame1 : IFrame
{
public void show()
{
Console.WriteLine("我是合金自行車架構1");
}
}
/// <summary>
/// 合金自行車架構2
/// </summary>
public class AlloyFrame2 : IFrame
{
public void show()
{
Console.WriteLine("我是合金自行車架構2");
}
}
/// <summary>
/// 真皮座椅1
/// </summary>
public class DermisSeat1 : ISeat
{
public void show()
{
Console.WriteLine("我是真皮座椅1");
}
}
/// <summary>
/// 真皮座椅2
/// </summary>
public class DermisSeat2 : ISeat
{
public void show()
{
Console.WriteLine("我是真皮座椅2");
}
}
/// <summary>
/// 結實的輪胎1
/// </summary>
public class SolidTire1 : ITire
{
public void show()
{
Console.WriteLine("我是結實的輪胎1");
}
}
/// <summary>
/// 結實的輪胎2
/// </summary>
public class SolidTire2 : ITire
{
public void show()
{
Console.WriteLine("我是結實的輪胎2");
}
}
自行車代碼:
/// <summary>
/// 自行車類
/// </summary>
public class Bike
{
/// <summary>
/// 自行車架構
/// </summary>
public IFrame frame { set; get; }
/// <summary>
/// 自行車座椅
/// </summary>
public ISeat seat { set; get; }
/// <summary>
/// 自行車 輪胎
/// </summary>
public ITire tire { set; get; }
/// <summary>
/// 擷取自行車的詳情資訊
/// </summary>
public void GetDetils()
{
Console.WriteLine("自行車的詳細資訊如下:");
frame.show();
seat.show();
tire.show();
}
}
抽象建築者和具體建築者:
/// <summary>
/// 抽象建築者類
/// 如果隻有一個具體的建築者類,則可以省略該抽象建築者類的
/// </summary>
public abstract class AbstractBuilder
{
public Bike mBike = new Bike();
public abstract void BuildFrame();
public abstract void BuildSeat();
public abstract void BuildTire();
/// <summary>
/// 傳回自行車對象
/// </summary>
/// <returns></returns>
public abstract Bike Build();
}
/// <summary>
/// 自行車建築者類1
/// </summary>
public class BikeBuilder1: AbstractBuilder
{
/// <summary>
/// 建構frame
/// </summary>
public override void BuildFrame()
{
mBike.frame = new AlloyFrame1();
}
/// <summary>
/// 建構seat
/// </summary>
public override void BuildSeat()
{
mBike.seat = new DermisSeat1();
}
/// <summary>
/// 建構tire
/// </summary>
public override void BuildTire()
{
mBike.tire = new SolidTire1();
}
/// <summary>
/// 傳回直行車對象
/// </summary>
/// <returns></returns>
public override Bike Build()
{
return mBike;
}
}
/// <summary>
/// 自行車建築者類2
/// </summary>
public class BikeBuilder2 : AbstractBuilder
{
/// <summary>
/// 建構frame
/// </summary>
public override void BuildFrame()
{
mBike.frame = new AlloyFrame2();
}
/// <summary>
/// 建構seat
/// </summary>
public override void BuildSeat()
{
mBike.seat = new DermisSeat2();
}
/// <summary>
/// 建構tire
/// </summary>
public override void BuildTire()
{
mBike.tire = new SolidTire2();
}
/// <summary>
/// 傳回直行車對象
/// </summary>
/// <returns></returns>
public override Bike Build()
{
return mBike;
}
}
指揮者:
/// <summary>
/// 指揮者
/// 調用建造者中的方法完成複雜對象的建立
/// 如果隻有一個建築者的話,可以省略該指揮者的角色
/// </summary>
public class BikeDirector
{
private AbstractBuilder _builder;
public BikeDirector(AbstractBuilder builder)
{
this._builder = builder;
}
/// <summary>
/// Bike的建構群組裝
/// </summary>
/// <returns></returns>
public Bike CreateBike()
{
_builder.BuildFrame();
_builder.BuildSeat();
_builder.BuildTire();
return _builder.Build();
}
}
測試代碼:
//1.普通模式
{
Console.WriteLine("-------------------下面是普通模式建構自行車-------------------------");
//1. 建構自行車
Bike b = new Bike();
b.frame = new AlloyFrame1();
b.seat = new DermisSeat2();
b.tire = new SolidTire1();
//2. 輸出自行車資訊
b.GetDetils();
}
//2. 使用建築者模式
{
Console.WriteLine("-------------------下面是使用建築者模式建構自行車-------------------------");
//1. 建構建築者
BikeBuilder1 builder = new BikeBuilder1();
builder.BuildFrame();
builder.BuildSeat();
builder.BuildTire();
//2. 建構自行車
Bike bike = builder.Build();
//3. 輸出自行車的資訊
bike.GetDetils();
}
//3. 引入抽象建築者父類
{
Console.WriteLine("-------------------下面是 引入抽象建築者父類 建構自行車-------------------------");
//1. 建構建築者1
AbstractBuilder builder = new BikeBuilder1();
builder.BuildFrame();
builder.BuildSeat();
builder.BuildTire();
//2. 建構自行車
Bike bike = builder.Build();
//3. 輸出自行車的資訊
bike.GetDetils();
//1. 建構建築者2
AbstractBuilder builder2 = new BikeBuilder2();
builder2.BuildFrame();
builder2.BuildSeat();
builder2.BuildTire();
//2. 建構自行車
Bike bike2 = builder2.Build();
//3. 輸出自行車的資訊
bike2.GetDetils();
}
//4. 引入指揮者
{
Console.WriteLine("-------------------下面是 引入指揮者 建構自行車-------------------------");
//指揮者1
BikeDirector dirctor1 = new BikeDirector(new BikeBuilder1());
Bike bike1 = dirctor1.CreateBike();
bike1.GetDetils();
//指揮者2
BikeDirector dirctor2 = new BikeDirector(new BikeBuilder2());
Bike bike2 = dirctor2.CreateBike();
bike2.GetDetils();
}
運作效果:
4. 适用場景分析
建造者(Builder)模式建立的是複雜對象,其産品的各個部分經常面臨着劇烈的變化,但将它們組合在一起的算法卻相對穩定,是以它通常在以下場合使用。
A. 建立的對象較複雜,由多個部件構成,各部件面臨着複雜的變化,但構件間的建造順序是穩定的。
B. 建立複雜對象的算法獨立于該對象的組成部分以及它們的裝配方式,即産品的建構過程和最終的表示是獨立的。
原文連結:https://www.cnblogs.com/yaopengfei/p/13462519.html