设计模式之-代理模式

代理模式

代理模式是一个使用率非常高的模式,其定义如下:Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。)

代理模式在各类开发中运用的相当广泛,不论是j2ee,android还是ios,都能看到它的身影,所以说设计模式无处不在。代理模式,字面理解就是自己不方便做或者不能做的事情,需要第三方代替来做,最终通过第三方来达到自己想要的目的或效果。举例了:员工小李在B总公司打工,B总成天让小李加班不给加班费,小李忍受不住了,就想去法院告B总。虽然法律上允许打官司不请律师,允许自辩。但是小李第一不熟悉法律起诉的具体流程,第二嘴比较笨,人一多腿就抖得厉害。因此,小李决定去找律师帮忙打官司。找律师打官司和自己打官司相比,有相同的地方,也有不同的地方。

相同的地方

1.都需要提交原告的资料,如姓名、年龄、事情缘由、想达到的目的。
2. 都需要经过法院的取证调查,开庭争辩等过程。
3. 最后拿到审判结果。

不同的地方

1、 小李省事了,让专业的人做专业的事,不需要自己再去了解法院那一套繁琐复杂的流程。
2、 把握更大了。

通过上面的例子,我们注意到代理模式有几个重点。
1、 被代理的角色(小李)
2、 代理角色(律师)
3、 协议(不管是代理和被代理谁去做,都需要做的事情,抽象出来就是协议)

下面给个例子

public class Proxy {
       public static void main(String[] args) {
              Employer employer=new Employer();
              System.out.println("我受不了了,我要打官司告老板");
              System.out.println("找律师解决一下吧......");
              Protocol lawyerProxy=new LawyerProxy(employer);
              lawyerProxy.register("Forest");
              lawyerProxy.dosomething();
              lawyerProxy.notifys();
       }
}
interface Protocol{
       //登记资料
       public void register(String name);
       //调查案情,打官司
       public void dosomething();
       //官司完成,通知雇主
       public void notifys();
}
//律师类
class LawyerProxy  implements Protocol{
       private Employer employer;
       public LawyerProxy(Employer employer){
              this.employer=employer;
       }
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.employer.register(name);
       }

       public void collectInfo(){
              System.out.println("作为律师,我需要根据雇主提供的资料,整理与调查,给法院写出书面文字,并提供证据。");
       }
       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              collectInfo();
              this.employer.dosomething();
              finish();
       }
       public void finish(){
              System.out.println("本次官司打完了...............");

       }
       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              this.employer.notifys();
       } 
}
//雇主类
class Employer implements Protocol{
       String name=null;
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.name=name;
       }

       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              System.out.println("我是'"+this.name+"'要告B总,他每天让我不停的加班,还没有加班费。");
       }

       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              System.out.println("法院裁定,官司赢了,B总需要赔偿10万元精神补偿费。");
       }

}

运行后,打印如下:

我受不了了,我要打官司告老板

找律师解决一下吧……

作为律师,我需要根据雇主提供的资料,整理与调查,给法院写出书面文字,并提供证据。

我是’Forest’要告B总,他每天让我不停的加班,还没有加班费。

本次官司打完了……………

法院裁定,官司赢了,B总需要赔偿10万元精神补偿费。

代码说明:

Protocol这个类就是上面所说的协议,是被代理者或者代理者共同遵守的约定。也就是说,无论是原告还是代理律师,到法院走程序,都需要做的事情。我们抽象出来,这个就是协议。

Employer这类是雇主类也称被代理者类,它遵从Protocol协议,并实现了Protocol协议的三个方法,并去分别完成了具体事情。

LawyerProxy这类是代理类,它也遵从Protocol协议,与Employer不同的是,定义了一个Employer对象,通过构造函数初始化。在实现的三个方法里,分别去调用被代理类的相同实现。就好比去模拟一个被告者,站在被告的角度上,去法院告状。也就是说LawyerProxy代理类对所有想打官司的人开放,只要有原告进来,我就帮他打官司。值得注意的是collectInfo和finish这两个函数,请律师打官司和不请律师打官司,其实都要做同样的事情(register、dosomething、notifys),但是至于为什么?刚才不是说了吗,请律师的好处是省心并且专业,他在做同样的事情前提下,还会收集对你有利的证据和资料(collectInfo),以及后续事情的处理(finish)。

上面就是最普通的代理模式,引申一点,我们看到,对于被告来说,必须创建一个Employer类,并实例化后传参给LawyerProxy代理类,这样做,是不是暴漏了Employer?如果隐藏一下,对于被告来说,更智能傻瓜一点,该怎么做呢?
public class Proxy {
       public static void main(String[] args) {
              //Employer employer=new Employer();
              System.out.println("我受不了了,我要打官司告老板");
              System.out.println("找律师解决一下吧......");
              Protocol lawyerProxy=new LawyerProxy("Forest"); 
              lawyerProxy.dosomething();
              lawyerProxy.notifys();
       }
}
interface Protocol{
       //登记资料
       public void register(String name);
       //调查案情,打官司
       public void dosomething();
       //官司完成,通知雇主
       public void notifys();
}
//律师类
class LawyerProxy  implements Protocol{
       private Employer employer;
       public LawyerProxy(String name){
              if(name==null) {
                     System.out.println("谁告状?逗我玩呢吧?");
                     return;
              }
              if(employer==null) employer=new Employer();
              register(name); 
       }
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.employer.register(name);
       }

       public void collectInfo(){
              System.out.println("作为律师,我需要根据雇主提供的资料,整理与调查,给法院写出书面文字,并提供证据。");
       }
       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              collectInfo();
              this.employer.dosomething();
              finish();
       }
       public void finish(){
              System.out.println("本次官司打完了...............");

       }
       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              this.employer.notifys();
       } 
}
//雇主类
class Employer implements Protocol{
       String name=null;
       @Override
       public void register(String name) {
              // TODO Auto-generated method stub
              this.name=name;
       }

       @Override
       public void dosomething() {
              // TODO Auto-generated method stub
              System.out.println("我是'"+this.name+"'要告B总,他每天让我不停的加班,还没有加班费。");
       }

       @Override
       public void notifys() {
              // TODO Auto-generated method stub
              System.out.println("法院裁定,官司赢了,B总需要赔偿10万元精神补偿费。");
       }

}

看到没new LawyerProxy(“Forest”),只需要给代理类传入简单的名字,隐含了Employer类,代理类就会自动去创建一个Employer实例,模拟一个用户继续替你完成打官司的事情。

在这种改造下,系统更加简洁了,调用者只知道代理存在就可以,不用知道代理了谁。

这种模式,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模块没有任何的影响,只要你实现了接口所对应的方法,这种模式非常适合对扩展性要求较高的场合。当然,在实际的项目中一般都是通过约定来禁止new一个真实的角色,这也是一个非常好的方案

代理模式还有一种就是强制代理,为什么这么说?一般的思维都是通过代理找到真实的角色,但是强制代理却是要“强制”,你必须通过真实角色查找到代理角色,否则你不能访问,不管你是直接new一个主题角色都不能访问,只有通过真实角色指定的代理类才可以访问
例子代码如下

public class Proxy {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Employer employer=new Employer();
        System.out.println("我受不了了,我要打官司告老板");
        System.out.println("找律师解决一下吧......");
        Protocol lawyerProxy=new LawyerProxy(employer);
        lawyerProxy.register("Forest");
        lawyerProxy.dosomething();
        lawyerProxy.notifys();

    }

}
interface Protocol{
    //登记资料
    public void register(String name);
    //调查案情,打官司
    public void dosomething();
    //官司完成,通知雇主
    public void notifys();
    //每个人都露找一下自己的代理
    public Protocol getProxy();
}
//律师类
class LawyerProxy implements Protocol{
    private Employer employer;
    public LawyerProxy(Employer employer){
        this.employer = employer;
    }


    @Override
    public void register(String name) {
        // TODO Auto-generated method stub
        this.employer.register(name);
    }
    public void collectInfo(){
        System.out.println("作为律师,我需要根据雇主提供的资料,整理与调查,给法院写出书面文字,并提供证据。");
    }

    @Override
    public void dosomething() {
        // TODO Auto-generated method stub
        collectInfo();
        this.employer.dosomething();
         finish();

    }
    public void finish(){
        System.out.println("本次官司打完了...............");

 }

    @Override
    public void notifys() {
        // TODO Auto-generated method stub
        this.employer.notifys();
    }


    @Override
    public Protocol getProxy() {
        // TODO Auto-generated method stub
        return this;
    }

}
//雇主类
class Employer implements Protocol{
    String name = null;
    private Protocol proxy = null;
    @Override
    public void register(String name) {
        // TODO Auto-generated method stub
        this.name = name;


    }

    @Override
    public void dosomething() {
        // TODO Auto-generated method stub
        if(isProxy()){
            System.out.println("我是'"+this.name+"'要告B总,他每天让我不停的加班,还没有加班费。");
        }else{
            System.out.println("请用代理模式访问");
        }

    }

    @Override
    public void notifys() {
        // TODO Auto-generated method stub
        if(isProxy()){
            System.out.println("法院裁定,官司赢了,B总需要赔偿10万元精神补偿费。");
        }else{
            System.out.println("请用代理模式访问");
        }

    }

    @Override
    public Protocol getProxy() {
        // TODO Auto-generated method stub
        this.proxy = new LawyerProxy(this);
        return this.proxy;
    }
    //校验是否是代理访问
    private boolean isProxy(){
        if(this.proxy == null){
            return false;
        }else{
            return true;
        }
    }

}

执行的结果你会发现提示你“使用代理模式访问”
原因在开始的时候已经说过了,在这里我们只需要在main方法里修改一些即可

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Employer employer=new Employer();
        System.out.println("我受不了了,我要打官司告老板");
        System.out.println("找律师解决一下吧......");
        Protocol lawyerProxy=employer.getProxy();
        lawyerProxy.register("Forest");
        lawyerProxy.dosomething();
        lawyerProxy.notifys();

    }

最后做个总结:
代理模式的优点:

*职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事物,通过后期的代理完成一件事物,附带的结果就是变成简介清晰。

*高扩展性
具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不出接口,那我们的代理类完全就可以在不做任务修改的情况下使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值