用心理解設計模式——代理模式 (Proxy Pattern)
阿新 • • 發佈:2018-11-21
前置文章: 用心理解設計模式——設計模式的原則
設計模式相關程式碼已統一放至 我的 Github
一、定義
結構型模式之一。
Provide a surrogate or placeholder for another object to control acess to ot.
(為其他物件提供一種代理,以控制對這個物件的訪問)
二、結構解析
代理模式的一般結構有三種角色:抽象主題、真實主題(被代理者)、代理者。
抽象主題,負責定義和宣告真實主題要被代理的業務方法介面。
真實主題,繼承抽象主題,實現自己真實的業務方法介面。
代理者,也繼承抽象主題,擁有與真實主題(被代理者)相同的要被代理的業務方法介面, 從外觀上看代理者與被代理者似乎一樣。代理者內部依賴真實主題,實現這些業務方法介面時,最終呼叫了真實主題(被代理者)的業務方法,但可以在預先或之後進行了一些額外的處理。
三、評價
代理模式封裝了客戶訪問或控制真實主題(被代理者)的過程,充當代理作用,解除了客戶和真實主題之間的直接耦合。
各自職責變得清晰,符合開閉原則, 非常易擴充套件。
在真實主題不唯一, 但代理過程相同時,只需新增真實主題類即可(對擴充套件開放),而不用修改已有的代理類和已有的真實主題類(對修改關閉)。
在真實主題唯一, 但代理過程不同時,只需新增滿足需求的代理類(對擴充套件開放),而不用修改已有的代理類和已有的真實主題類(對修改關閉)。
在真實主題唯一, 代理過程也不同時,可以同時擴充套件且不用修改已有的代理類和已有的真實主題類。
四、實現
namespace Proxy { //抽象主題 public abstract class Subject { //定義和宣告真實主題要被代理的業務方法介面 public abstract void DoSth(); } //真實主題 public class RealSubject : Subject { //實現業務方法介面,真實要做的事情。 public override void DoSth(){} } //代理者 public class Proxy : Subject { //內部依賴真實主題 private Subject subject = new RealSubject(); //代理者擁有與真實主題(被代理者) public override void DoSth() { //額外的預先操作 this.Before(); //最終呼叫真實主題的業務方法 this.subject.DoSth(); //額外的後續操作 this.After(); } private void Before() { } private void After() { } } public class Client { static public void Main() { Proxy proxy = new Proxy(); proxy.DoSth(); } } }
五、真實主題和代理過程擴充套件
namespace Proxy.ExpandBoth
{
public abstract class Subject
{
public abstract void DoSth();
}
//真實主題A
public class RealSubjectA : Subject
{
public override void DoSth() { }
}
//真實主題B
public class RealSubjectB : Subject
{
public override void DoSth() { }
}
//代理X
public class ProxyX : Subject
{
//在構造代理者時確定代理哪個真實主題
private Subject subject = null;
public ProxyX(Subject subject)
{
this.subject = subject;
}
public override void DoSth()
{
this.BeforeX();
this.subject.DoSth();
this.AfterX();
}
private void BeforeX() { }
private void AfterX() { }
}
//代理Y
public class ProxyY : Subject
{
//在構造代理者時確定代理哪個真實主題
private Subject subject = null;
public ProxyY(Subject subject)
{
this.subject = subject;
}
public override void DoSth()
{
this.BeforeB();
this.subject.DoSth();
this.AfterB();
}
private void BeforeB() { }
private void AfterB() { }
}
public class Client
{
static public void Main()
{
RealSubjectA realSubjectA = new RealSubjectA();
RealSubjectB realSubjectB = new RealSubjectB();
//X代理真實主題A
ProxyX proxyXA = new ProxyX(realSubjectA);
proxyXA.DoSth();
//X代理真實主題B
ProxyX proxyXB = new ProxyX(realSubjectB);
proxyXB.DoSth();
//Y代理真實主題A
ProxyY proxyYA = new ProxyY(realSubjectA);
proxyYA.DoSth();
//Y代理真實主題B
ProxyY proxyYB = new ProxyY(realSubjectB);
proxyYB.DoSth();
}
}
}
六、動態代理
TODO