跟屌丝大哥学习设计模式---代理模式

代理模式是我们比较常用的设计模式之一。其中新思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信,代理模式一般涉及到的角色有: 

抽象角色:声明真实对象和代理对象的共同接口; 

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。 

真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

 

以下以发送消息为例来说明一个简单的代理模式的基本实现:

首先明确目的:有一条消息,需要把这个消息发送出去,根据这个目的定义对应接口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;
@Override
public void sendMessage(String msg) {
// TODO Auto-generated method stub
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 && msg.length() > 10;
}
}
//调用类
public class MainClass {
private static void runProxy(MessageHandler handler)
{
handler.sendMessage("message for test");
}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
runProxy(new EmailMessage());
System.out.println("++++++++++++++++Pjroxy++++++++++++++++++");
runProxy(new MessageProxy());
}
}
输出
message for test send!!
++++++++++++++++Pjroxy++++++++++++++++++
message for test send!!
Message sent:1

在例子中我们可以方便的在消息发送过程中添加各种需要的附加处理方式,也能方便的替换消息的处理方式,如将通过Email发送消息替换为通过短信发送消息,而调用方不会有丝毫察觉!在任何你想要将一些额外操作分离到具体对象之外,特别是希望能够很容易做出修改,或者想在具体对象的方法执行前插入一些额外操作的时候,代理就显得十分有用!

 例如:假设有一组对象都实现同一个接口,实现同样的方法,但这组对象中有一部分对象需要有单独的方法,传统的笨办法是在每一个应用端都加上这个单独的方法,但是代码重用性低,耦合性高。   如果用代理的方法则很好的解决了这个问题
 假设有一个Italk接口,有空的方法talk()(说话),所有的people对象都实现(implements)这个接口,实现talk()方法, 前端有很多地方都将people实例化,执行talk方法,后来发现这些前端里有一些除了要说话以外还要唱歌(sing),那么我们既不能在Italk接 口里增加sing()方法,又不能在每个前端都增加sing方法,我们只有增加一个代理类talkProxy,这个代理类里实现talk和sing方法, 然后在需要sing方法的客户端调用代理类即可,代码如下:

接口类Italk

  public interface Italk { 
  public void talk(String msg); 
  }

实现类people

  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); 
  }   
}

代理类talkProxy

  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); 
  }  
 } 
  }

应用端myProxyTest

  public class MyProxyTest {  
 /**代理模式   * @param args   */  
 public static void main(String[] args)
 {   
//不需要执行额外方法的  
 Italk people1=new People("湖海散人","18");  
 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 {
@Override
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;
}

@Override
public void buyTicket() {
   // TODO Auto-generated method stub
   System.out.println("通过代售点");
   passenger.buyTicket();
}
}

//测试类
public class Client {
public static void main(String[] args) {
   Passenger passenger = new RealPassenger();
   Passenger proxy = new Proxy(passenger);
   proxy.buyTicket();
}
}

输出结果:
通过代售点
购买了火车票

以 上的也可叫做静态代理,是为了区别代理模式在Java中的另一种实现——动态代理。

接下来会为大家带来动态代理








====================================分割线================================



最新内容请见作者的GitHub页:http://qaseven.github.io/

上一篇:CImage类


下一篇:转-阿里云CentOS Linux服务器上用postfix搭建邮件服务器