代理模式

代理模式

平时我们生活中的代理,是指类似中介的角色,能够代理某一公司或机构帮助我们完成一类事情,同理,代码世界中的代理模式,也差不多是这样,先来看一下代理模式的类图:

 

 上面的Subject是一个公有接口,提供了一系列的能力,比如,房产公司就是一个公有接口,提供了房产交易的功能。

  Proxy可以认为是房产中介,实现了Subject接口,也就是说 Proxy代理了Subject,房产中介需要知道具体客户的信息,所以Proxy内部需要维护一个RealSubject。

  RealSubject则是购房者,也实现了Subject接口。(为什么购房者需要实现一个房产公司接口呢?可以理解为,购房者需要和房产公司建立了联系,才能进行房产买卖,至于买卖方式,是分期还是全款,是线上支付还是线下支付,这个看具体的购房者)

 下面是示例代码:

EstateCompany类(代表Subject公有接口):

public interface EstateCompany {
     void tradeRealEstate();
}

 

RealCustomer类(代表RealSubject):

复制代码

public class ReealCustomer implements EstateCompany{
    private String name;
    
     public ReealCustomer(String name) {
         this.name = name;
         
        // TODO Auto-generated constructor stub
    }

    @Override
    public void tradeRealEstate() {
        // TODO Auto-generated method stub
        System.err.println(name+"去银行取了五百万买房");
        
    }

}

复制代码

 

ProxyWorker类(代表 Proxy):

复制代码

public class ProxyWorker implements EstateCompany{
    private ReealCustomer mCustomer; 
    
     public void setmCustomer(EstateCompany realEstateCompany) {
        this.mCustomer = (ReealCustomer) realEstateCompany;
    }

    @Override
    public void tradeRealEstate() {
        // TODO Auto-generated method stub
        System.err.println("中介想办法找客户");
        mCustomer.tradeRealEstate();
        System.err.println("办理相关手续,成交了一套房子 ");
        
    }
    
}

复制代码

 

Client类:

复制代码

public class Client {
    public static void main(String[] args) {
        ReealCustomer customer = new ReealCustomer("陈先生");
        ProxyWorker proxyWorker = new ProxyWorker();
        proxyWorker.setmCustomer(customer);
        proxyWorker.tradeRealEstate();
    }
}

复制代码

 

 运行Client,得到日志:

至此,就是一个Java静态代理模式的运用。这样做的好处是什么呢?个人理解,是可以解耦。从上面Client调用时就可看到,只需要给ProxyWorker设置一个Customer,再调用tradeRealEstate,就可以完成房产交易,在调用的地方是看不到交易的细节的。交易细节很好地被隐藏了,而且ProxyWorker还可以扩展一些功能。

静态代理也有以下缺点:比如在上述例子中,想给EstateCompany增加一个积分返现的方法,那么,实现了该接口的所有类都要做出修改。

再者,代理类也会比较多,比如ProxyWorkerA只能卖南山区的房子,ProxyWorkerB只能卖罗湖区的房子,ProxyWorkerC只能卖福田区的房子,那为了客户可以随时看房子,房产公司就要先雇佣ProxyWorkerA、ProxyWorkerB、ProxyWorkerC,假如一直没有客户,岂不是浪费成本?有哥们可能会说,直接把ProxyWorkerA、ProxyWorkerB、ProxyWorkerC的功能写在一个ProxyWorker里不可以吗,当然可以,只不过这样ProxyWorker里的代码就会比较多,而且可能有较多重复代码,这样肯定不是一个比较好的做法。

把类写简洁,一般就意味着类要多点,但是又不想接口类写得太多造成所谓类爆炸,这,有点强人所难啊。。。

这时,一个牛逼的代理出现了,他说,根本不需要请三个代理,我可以在客户需要ProxyWorkerA的时候化身ProxyWorkerA,在客户需要ProxyWorkerB的时候化身ProxyWorkerB。公司出了新政策和有什么活动要搞,你不用再费力气去分别通知三个代理了,你只需要通知客户就可以了,连我都不需要通知,我自己有办法知道这些政策和活动。

这个牛逼的代理就是动态代理。下面来看示例代码:

 

EstateCompany类:

public interface EstateCompany {
     void tradeRealEstate();
}

 

 ReealCustomer类:

复制代码

public class ReealCustomer implements EstateCompany{
    private String name;
    
     public ReealCustomer(String name) {
         this.name = name;
         
        // TODO Auto-generated constructor stub
    }

    @Override
    public void tradeRealEstate() {
        // TODO Auto-generated method stub
        System.err.println(name+"去银行取了五百万买房");
        
    }

}

复制代码

 

 ProxyFactory类取代了ProxyWorker类:

复制代码

public class ProxyFactory{
    
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

   //获取罗湖区的代理对象
    public Object getLuoHuProxy(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("先去看看罗湖区的房子");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("成交了罗湖区的一套房子");
                        return returnValue;
                    }
                }
        );
    }
    
  //获取福田区的代理对象
    public Object getFuTianProxy(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("先去看看福田区的房子");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("成交了福田区的一套房子");
                        return returnValue;
                    }
                }
        );
    }
}

复制代码

 

Client类:

复制代码

public class Client {
    public static void main(String[] args) {
        ReealCustomer customer = new ReealCustomer("陈先生");
        EstateCompany object = (EstateCompany) new ProxyFactory(customer).getLuoHuProxy();
        object.tradeRealEstate();
    }

}

复制代码

 

 打印结果:

 

可以看到,在client中,已经无需创建ProxyWorker类,如果需要增加看光明区的房子的代理,只需要在 ProxyFactory中增加一个getGuangmingProxy(),在该方法中做相应逻辑并返回Object即可,

而且EstateCompany接口有修改,只需要在ReealCustomer中修改即可,不需要修改ProxyFactory。

 

值得注意的是,ProxyFactory下图中箭头所指方法不是顺序执行的,它们执行的顺序是随机的

 

 比如,也可以得到如下结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值