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

    xiaoxiao2023-11-20  168

    什么用

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

    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)