【設計模式】-代理模式、介面卡模式、橋接模式、中介者模式
前言
從字面意思上感覺代理、介面卡、橋接、中介者有很大的共性。通過這樣的對比學習讓我們深入瞭解一下這四種模式吧。
代理模式
為其他物件提供一種代理以控制對這個物件的訪問。使用者不想或者不能直接引用一個物件,而代理物件可以在使用者與物件之間起到中介的作用。例如桌面上的快捷方式則是應用程式的一個代理。下面是代理模式的結構圖:
舉個例子:拖朋友去國外買iPhone
建立抽象主題類:
建立具體主題類:
建立代理類:
客戶端程式碼:
優點
- 降低了使用者與物件直接的耦合度。
- 可以擴充套件具體的主題類或者主題類的功能,擴充套件性好。
缺點
- 由於增加了一個代理物件,導致請求速度變慢。
- 增加了系統的複雜性
介面卡模式
將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不相容而不能在一起工作的那些類可以一起工作。下面為介面卡模式的結構圖:
舉個栗子:我家電器插頭是兩頭的,而插排都是三頭的,我們現在希望把三頭插頭轉換為兩頭插頭。
建立一個需要適配的三頭插頭的類或介面:
建立一個使用者期待的兩頭插頭的類:
建立一個介面卡類:
客戶端程式碼:
優點
將目標類和介面卡者類解耦,增加了類的複用性,在不修改原始碼的基礎上來複用現有類,符合開閉原則
缺點
一次最多隻能適配一個適配者類,不能同時適配多個適配者。
橋接模式
將抽象部分與它的實現部分分離,使它們都可以獨立地變化。下面為橋接模式的結構圖:
舉個栗子:電視都有遙控器,我們可以把遙控器當做一個抽象類,抽象類中提供遙控器所有功能的實現,當然其他的遙控器也繼承這個抽象類。
建立抽象類或者介面、集體的實現類:電視類和集體的實現方法
public abstract class TV
{
public abstract void On();
public abstract void Off();
public abstract void Set();
}
public class Samsung : TV
{
public override void On()
{
Console.WriteLine("開啟三星電視");
}
public override void Off()
{
Console.WriteLine("關閉三星電視");
}
public override void Set()
{
Console.WriteLine("更換三星電視訊道");
}
}
public class SONY : TV
{
public override void On()
{
Console.WriteLine("開啟索尼電視");
}
public override void Off()
{
Console.WriteLine("關閉索尼電視");
}
public override void Set()
{
Console.WriteLine("更換索尼電視訊道");
}
}
建立抽象類、被提煉的抽象:遙控器及要擴充的功能
public class RemteControl //遙控器
{
private TV implementor;
public TV Implementor
{
get { return implementor; }
set { implementor = value; }
}
public virtual void On()
{
implementor.On();
}
public virtual void Off()
{
implementor.Off();
}
public virtual void Set()
{
implementor.Set();
}
}
//要擴充的新功能,重寫了這個方法,注意base.set 很關鍵
public class ConcreteRemote : RemteControl
{
public override void Set()
{
base.Set();
Console.WriteLine("新功能");
}
}
客戶端程式碼和結果:
優點
- 把抽象介面與其實現解耦。
- 抽象和實現可以獨立擴充套件,不會影響到對方。擴充套件性極好
- 提高程式碼的複用性
缺點
- 增加了系統的複雜性,不容易區分,難維護。
中介者模式
用一箇中介物件來封裝一系列的物件互動。中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變他們之間的互動。下面是中介者模式的結構圖:
舉個栗子:租房,有租戶、租主、中介
建立抽象的同事類、抽象中介者:
//抽象中介者
public abstract class MediatorQ
{
public abstract void Show(string Message, Colleague colleague);
}
//抽象同事類
public abstract class Colleague
{
protected MediatorQ Mediator;
public Colleague(MediatorQ Mediator)
{
this.Mediator = Mediator;
}
}
具體的同事類:租戶和租主
//具體同事類:租戶
class Tenant : Colleague
{
public Tenant(MediatorQ Mediator) : base(Mediator)
{
}
public void Show(string message)
{
Mediator.Show(message, this);
}
public void GetMessage(string message)
{
Console.WriteLine("租住資訊:"+message);
}
}
//具體同事類:租主
class Landlord : Colleague
{
public Landlord(MediatorQ Mediator) : base(Mediator)
{
}
public void Show(string message)
{
Mediator.Show(message, this);
}
public void GetMessage(string message)
{
Console.WriteLine("租住資訊:"+message);
}
}
具體的中介:
//具體中介者
class ConcreataMediator : MediatorQ
{
//獲取租戶和租主的訊息,並賦值
private Tenant colleague1;
private Landlord colleague2;
public Tenant Colleague1
{
set { colleague1 = value; }
}
public Landlord Colleague2
{
set { colleague2 = value; }
}
//對抽象中介者方法進行宣告,實現兩個物件之間的通訊
public override void Show(string message, Colleague colleague)
{
if (colleague==colleague1)
{
colleague2.GetMessage(message);
}
else
{
colleague1.GetMessage(message);
}
}
客戶端程式碼:
static void Main(string[] args)
{
//例項一個具體的中介者
ConcreataMediator C = new ConcreataMediator();
//例項化具體租戶c1和租主c2
Tenant c1 = new Tenant(C);
Landlord c2 = new Landlord(C);
//獲得雙方資訊
C.Colleague1 = c1;
C.Colleague2 = c2;
c1.Show("我想住一個1000平米的房子");
c2.Show("我家房租符合您的要求");
Console.Read();
}
優點
- 減少物件之間直接互動所產生的錯誤,多個物件之間通過中介者來互動
- 同事之間解耦,提供系統的靈活性,使得各個同事物件獨立而易於複用
缺點
- 中介者模式中,中介者角色承擔了較多的責任,所以一旦這個中介者物件出現了問題,整個系統將會受到重大的影響
總結
雖然總結的時候會花很長時間,但是經過這樣的一個過程之後,發現這四個模式之間並沒有很大的共性,每個各有千秋,本來一個模式就是解決一個問題,謹慎使用!