每天一个设计模式(六)——代理模式

什么用

顾名思义,代理模式就是本该由客户直接调用某一目标对象,但却由于客户不想或不能或者由于其他某些原因,没有直接调用该对象,而是通过中间对象去调用目标对象。该中间对象即为代理,它不仅起到中介的作用,还能隐去客户不能看见的内容,或者添加客户需要的额外服务。

RMI调用就是一种代理模式。远程服务器中的服务在本地有一个stub代理,该代理封装了访问远程服务的方法,客户可通过该代理来调用远程服务。

Spring AOP也是一种代理。用户在调用原服务前后,添加的@Before和@AfterReturning注解,就是解决用户需求的新服务。

模式结构

  • 抽象主题角色:
    声明了代理主题角色和真是主题角色的公共接口。
  • 代理主题角色:
    封装了可以调用真实主题角色服务的方法。
  • 真实主题角色
    实现了用户所需要的真正的服务,用户通过代理主题角色使用该服务。

优缺点

优点
  • 一定程度上使用户与服务之间解耦,并且可以在原服务的基础上插入新的服务。
  • 远程代理可以使客户可以访问远程机器上的资源。
  • 虚拟代理可以先用小对象代表大对象,减少对资源的占用,当确实需要大对象时再创建大对象。
  • 保护代理可以控制对真实对象的使用权限。
缺点
  • 由于多了一层代理,可能会使处理速度变慢。
  • 有些代理模式的实现可能比较复杂。

适用情况

  • 远程代理:当本地客户端需要调用不同地址空间上的对象时,使用代理模式。这个不同地址空间可以是在另一台主机上。
  • 虚拟代理:当需要创建一个资源消耗较大的对象时,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
  • 保护代理:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
  • 智能引用代理:当一个对象被引用时,提供一些额外的操作,如在使用前后打印日志。
  • 缓冲代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。

实际应用

  • RMI机制
  • Spring AOP

代码示例

https://github.com/zero4eva/design_pattern

这里实现的对登录进行代理设置,只是为了打印日志封装出来的。实际上可以使用Spring AOP对所
有request和response进行打印日志。

  • LoginTest.java

    public class LoginTest {
        public static void main(String[] args) {
            String name = "admin";
            String password = "admin";
            
            LoginServiceProxy loginServiceproxy = new LoginServiceProxy();
            boolean loginSuccess = loginServiceproxy.login(name, password);
            if (loginSuccess){
                System.out.println("login success!");
            }else{
                System.out.println("login failed!");
            }
        }
    }
    
  • ILoginService.java

    public interface ILoginService {
        public boolean login(String name, String password);
    }
    
  • LoginServiceImpl.java

    public class LoginServiceImpl implements ILoginService {
        @Override
        public boolean login(String name, String password) {
            return "admin".equals(name) && "admin".equals(password);
        }
    }
    
  • LoginServiceProxy.java

    public class LoginServiceProxy implements ILoginService{
    
        LoginServiceImpl loginService;
    
        public LoginServiceProxy() {
            loginService = new LoginServiceImpl();
        }
    
        @Override
        public boolean login(String name, String password) {
            beforeService(name, password);
            boolean ret = loginService.login(name, password);
            afterService(ret);
            return ret;
        }
    
        public void beforeService(String name, String password) {
            System.out.println("-----------------------------------------------------------------");
            System.out.println("login info: ");
            System.out.println("    name: " + name + ", password: " + password);
        }
    
        public void afterService(boolean loginResult) {
            System.out.println("login result: " + loginResult);
            System.out.println("-----------------------------------------------------------------");
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值