天天看點

跟屌絲大哥學習設計模式---代理模式

<a href="http://www.cnblogs.com/hjzhang/archive/2010/06/15/2043568.html">java 代理模式詳解</a>

代理模式是我們比較常用的設計模式之一。其中新思想是為了提供額外的處理或者不同的操作而在實際對象與調用者之間插入一個代理對象。這些額外的操作通常需要與實際對象進行通信,代理模式一般涉及到的角色有: 

抽象角色:聲明真實對象和代理對象的共同接口; 

代理角色:代理對象角色内部含有對真實對象的引用,進而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當于對真實對象進行封裝。 

真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。

以下以發送消息為例來說明一個簡單的代理模式的基本實作:

首先明确目的:有一條消息,需要把這個消息發送出去,根據這個目的定義對應接口messagehandler。需要的附加操作:假設需要驗證消息的長度不能超過指定長度并且不能為空,并且我們需要統計相關資訊發送到次數,超過指定的次數我們需要輸出警報。我們通過代理模式來實作這個附加的操作。下面為對應的類關系圖及示例代碼。

//接口定義

public interface messagehandler {

public void sendmessage(string msg);

}

//通過email方式發送消息的實作類

public class emailmessage implements messagehandler {

@override

public void sendmessage(string msg) {

// todo auto-generated method stub

system.out.println(msg+" send!!");

//消息處理的代理類

public class messageproxy implements messagehandler {

private static int count;

private messagehandler emailmsg;

if(checkmessage(msg))

{

if(emailmsg==null) emailmsg=new emailmessage();

count++;

emailmsg.sendmessage(msg);

system.out.println("message sent:"+count);

private boolean checkmessage(string msg) {

return msg != null &amp;&amp; msg.length() &gt; 10;

//調用類

public class mainclass {

private static void runproxy(messagehandler handler)

handler.sendmessage("message for test");

/**

 * @param args

 */

public static void main(string[] args) {

runproxy(new emailmessage());

system.out.println("++++++++++++++++pjroxy++++++++++++++++++");

runproxy(new messageproxy());

輸出

message for test send!!

++++++++++++++++pjroxy++++++++++++++++++

message sent:1

在例子中我們可以友善的在消息發送過程中添加各種需要的附加處理方式,也能友善的替換消息的處理方式,如将通過email發送消息替換為通過短信發送消息,而調用方不會有絲毫察覺!在任何你想要将一些額外操作分離到具體對象之外,特别是希望能夠很容易做出修改,或者想在具體對象的方法執行前插入一些額外操作的時候,代理就顯得十分有用!

 例如:假設有一組對象都實作同一個接口,實作同樣的方法,但這組對象中有一部分對象需要有單獨的方法,傳統的笨辦法是在每一個應用端都加上這個單獨的方法,但是代碼重用性低,耦合性高。   如果用代理的方法則很好的解決了這個問題

 假設有一個italk接口,有空的方法talk()(說話),所有的people對象都實作(implements)這個接口,實作talk()方法, 前端有很多地方都将people執行個體化,執行talk方法,後來發現這些前端裡有一些除了要說話以外還要唱歌(sing),那麼我們既不能在italk接 口裡增加sing()方法,又不能在每個前端都增加sing方法,我們隻有增加一個代理類talkproxy,這個代理類裡實作talk和sing方法, 然後在需要sing方法的用戶端調用代理類即可,代碼如下:

  public interface italk { 

  public void talk(string msg); 

  }

  public class people implements italk

 {   public string username;  

 public string age;  

 public string getname() 

{   

return username; 

  }   

public void setname(string name) { 

  this.username= name;   

}  

 public string getage() {  

 return age;   }   

public void setage(string age) { 

  this.age = age;   }  

 public people(string name1, string age1) { 

  this.username= name1;  

 this.age = age1;  

 } 

  public void talk(string msg) { 

  system.out.println(msg+"!你好,我是"+username+",我年齡是"+age); 

  public class talkproxy implements italk

 {   italk talker;  

 public talkproxy (italk talker) 

  //super();   

this.talker=talker;  

 }   

public void talk(string msg) 

talker.talk(msg);  

public void talk(string msg,string singname)

 {   

talker.talk(msg); 

  sing(singname); 

private void sing(string singname)

{  

 system.out.println("唱歌:"+singname); 

  }  

  public class myproxytest {  

 /**代理模式   * @param args   */  

 public static void main(string[] args)

//不需要執行額外方法的  

 people1.talk("no proxy test");  

 system.out.println("-----------------------------");  

 //需要執行額外方法的   

talkproxy talker=new talkproxy(people1);   

talker.talk("proxy test","七裡香"); 

 }

所謂代理,是指具有與代理元(被代理的對象)具有相同的接口的類,用戶端必須通過代理與被代 理的目标類互動,而代理一般在互動的過程中(互動前後),進行某些特别的處理。proxy模式是很常見的模式,在我們生活中處處可見,例如我們買火車票不 一定非要到火車站去買,可以到一些火車票的代售點去買。寄信不一定是自己去寄,可以把信委托給郵局,由郵局把信送到目的地。

代理結構如下圖所示

跟屌絲大哥學習設計模式---代理模式

以通過代售點買火車票為例,代碼實作如下:

//提供買票的公共接口

interface passenger {

public void buyticket();

//乘客實體

public class realpassenger implements passenger {

public void buyticket() {

   // todo auto-generated method stub

   system.out.print("購買了火車票");

//代售點

public class proxy implements passenger {

passenger passenger;

public proxy(passenger p) {

   this.passenger = p;

   system.out.println("通過代售點");

   passenger.buyticket();

//測試類

public class client {

   passenger passenger = new realpassenger();

   passenger proxy = new proxy(passenger);

   proxy.buyticket();

輸出結果:

通過代售點

購買了火車票

以 上的也可叫做靜态代理,是為了差別代理模式在java中的另一種實作——動态代理。

接下來會為大家帶來動态代理

====================================分割線================================

最新内容請見作者的github頁:http://qaseven.github.io/