首页 > 其他分享 >代理模式

代理模式

时间:2023-01-17 13:33:40浏览次数:34  
标签:java 角色 void 代理 模式 proxy public

代理模式

即Proxy Pattern,23种java常用设计模式之一。代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问。

代理模式也是SpringAOP的底层

代理模式分类:

  • 静态代理
  • 动态代理

代理模式_java


1、静态代理

角色分析:

  • 抽象角色(Rent):一般使用接口或者抽象类
  • 真实角色(Host):被代理的真实角色
  • 代理角色(Proxy):中介,真实的代理的角色,且其一般还会添加一些附属操作
  • 客户(User):访问代理对象的用户
  1. 新建一个抽象角色类:Rent.java

    package pers.mobian.proxy.demo1;
    
    public interface Rent {
        public void rent();
    }
    
  2. 新建一个真实角色类:Host.java

    package pers.mobian.proxy.demo1;
    
    public class Host implements Rent {
        
        @Override
        public void rent() {
            System.out.println("我是房东,我有房子出租");
        }
    }
    
  3. 新建一个代理角色类:Proxy.java

    package pers.mobian.proxy.demo1;
    
    public class Proxy implements Rent{
    
        private Host host = new Host();
        @Override
        public void rent() {
            seeHouse();
            host.rent();
            signContract();
        }
    
        private void seeHouse(){
            System.out.println("中介带你看房子");
        }
        private void signContract(){
            System.out.println("中介帮忙签合同");
        }
    }
    
  4. 新建一个用户测试类:User.java

    package pers.mobian.proxy.demo1;
    
    public class User {
        public static void main(String[] args) {
            Proxy proxy = new Proxy();
            proxy.rent();
        }
    }
    
  5. 测试结果

    中介带你看房子
    我是房东,我有房子出租
    中介帮忙签合同
    

代理模式的优点:

  • 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共的业务交给了代理角色,实现了业务的分工
  • 公共业务发生扩展的时候,方便进行集中管理

缺点:

  • 一个真实角色会产生一个代理角色,开发效率变低

2、静态代理加强版

角色分析:

  • 抽象角色(UserService):包含增删改查四个方法
  • 真实角色(UserServiceImpl):增删改查的具体实现
  • 代理角色(Proxy):中介,真实的代理的角色,添加打印功能
  • 客户(User):访问代理对象的用户
  1. 抽象角色:UserService.java

    package pers.mobian.proxy.demo2;
    
    public interface UserService {
        public void add();
    
        public void delte();
    
        public void update();
    
        public void selet();
    
    }
    
  2. 真实角色:UserServiceImpl.java

    package pers.mobian.proxy.demo2;
    
    public class UserServiceImpl implements UserService {
        @Override
        public void add() {
            System.out.println("使用了增加方法");
        }
    
        @Override
        public void delte() {
            System.out.println("使用了删除方法");
        }
    
        @Override
        public void update() {
            System.out.println("使用了修改方法");
        }
    
        @Override
        public void selet() {
            System.out.println("使用了查找方法");
        }
    }
    
  3. 代理角色:Proxy.java

    package pers.mobian.proxy.demo2;
    
    public class Proxy implements UserService {
        private  UserServiceImpl userServiceImpl;
    
        public void setUserServiceImpl(UserServiceImpl userServiceImpl) {
            this.userServiceImpl = userServiceImpl;
        }
    
        public Proxy(UserServiceImpl userServiceImpl) {
            this.userServiceImpl = userServiceImpl;
        }
    
        public Proxy() {
        }
    
        @Override
        public void add() {
            userServiceImpl.add();
            show("add");
        }
    
        @Override
        public void delte() {
            userServiceImpl.delte();
            show("delte");
        }
    
        @Override
        public void update() {
            userServiceImpl.update();
            show("update");
        }
    
        @Override
        public void selet() {
            userServiceImpl.selet();
            show("selet");
        }
    
    
        public void show(String method){
            System.out.println(method+"方法使用成功");
        }
    }
    
  4. 客户:User.java

    package pers.mobian.proxy.demo2;
    
    public class User {
        public static void main(String[] args) {
            UserServiceImpl userServiceImpl = new UserServiceImpl();
    
            Proxy proxy = new Proxy(userServiceImpl);
            proxy.add();
            proxy.delte();
            proxy.selet();
            proxy.update();
    
        }
    }
    
  5. 测试结果

    使用了增加方法
    add方法使用成功
    使用了删除方法
    delte方法使用成功
    使用了查找方法
    selet方法使用成功
    使用了修改方法
    update方法使用成功
    

实际开发中的模型(仅供参考)

代理模式_其他_02


3、动态代理

  • 动态代理和静态代理角色相同
  • 动态代理的代理是动态生成的,不是我们直接写出来的
  • 动态代理分类:
    • 基于接口的:JDK动态代理
    • 基于类:cglib
    • java字节码实现:javassist

需要了解两个类:Proxy:代理 , InvocationHandler:调用处理程序

动态代理的好处:

  • 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共的业务交给了代理角色,实现了业务的分工
  • 公共业务发生扩展的时候,方便进行集中管理
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口即可

角色分析:

  • 抽象角色(Rent):一般使用接口或者抽象类
  • 真实角色(Host):被代理的真实角色
  • 动态代理角色(ProxyInvocationHander):可以动态代理一个接口下的所有操作
  • 客户(User):访问代理对象的用户
  1. 抽象角色:Rent.java

    package pers.mobian.proxy.demo3;
    
    public interface Rent {
        public void rent();
    }
    
  2. 真实角色:Host.java

    package pers.mobian.proxy.demo3;
    
    public class Host implements Rent {
    
        @Override
        public void rent() {
            System.out.println("我是房东,我有房子出租");
        }
    }
    
  3. 动态代理角色:ProxyInvocationHander.java

    package pers.mobian.proxy.demo3;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyInvocationHander implements InvocationHandler {
        //被代理的接口
        private Rent rent;
        public void setRent(Rent rent) {
            this.rent = rent;
        }
    
        //通过接口得到代理类
        public Object getProxy() {
            return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
        }
    
        //对代理实例添加附属操作,并返回结果
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            seeHouse();
            Object result = method.invoke(rent, args);
            signContract();
            return result;
        }
    
    
        private void seeHouse(){
            System.out.println("中介带你看房子");
        }
        private void signContract(){
            System.out.println("中介帮忙签合同");
        }
    }
    
  4. 客户:User.java

    package pers.mobian.proxy.demo3;
    
    public class User {
        public static void main(String[] args) {
            Rent rent = new Host();
            ProxyInvocationHander pih = new ProxyInvocationHander();
            pih.setRent(rent);
            Rent proxy = (Rent) pih.getProxy();
            proxy.rent();
        }
    }
    
  5. 测试结果

    中介带你看房子
    我是房东,我有房子出租
    中介帮忙签合同
    

4、动态代理类加强版

角色分析:

  • 抽象角色(UserService):包含增删改查四个方法
  • 真实角色(UserServiceImpl):增删改查的具体实现
  • 代理角色(Proxy):中介,真实的代理的角色,添加打印功能
  • 客户(User):访问代理对象的用户
  1. 抽象角色:UserService.java

    package pers.mobian.proxy.demo2;
    
    public interface UserService {
        public void add();
    
        public void delte();
    
        public void update();
    
        public void selet();
    
    }
    
  2. 真实角色:UserServiceImpl.java

    package pers.mobian.proxy.demo2;
    
    public class UserServiceImpl implements UserService {
        @Override
        public void add() {
            System.out.println("使用了增加方法");
        }
    
        @Override
        public void delte() {
            System.out.println("使用了删除方法");
        }
    
        @Override
        public void update() {
            System.out.println("使用了修改方法");
        }
    
        @Override
        public void selet() {
            System.out.println("使用了查找方法");
        }
    }
    
  3. 代理角色:Proxy.java

    package pers.mobian.proxy.demo4;
    
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyInvocationHander implements InvocationHandler {
        //被代理的接口
        private UserService userService;
    
        public void setUserService(UserService userService) {
            this.userService = userService;
        }
    
        //通过接口得到代理类
        public Object getProxy() {
            return Proxy.newProxyInstance(this.getClass().getClassLoader(), userService.getClass().getInterfaces(), this);
        }
    
        //对代理实例添加附属操作,并返回结果
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = method.invoke(userService, args);
            //通过反射获得具体的方法名
            log(method.getName());
            return result;
        }
    
        public void log(String method) {
            System.out.println(method+"方法使用成功");
        }
    }
    
  4. 客户:User.java

    package pers.mobian.proxy.demo4;
    
    public class User {
        public static void main(String[] args) {
            UserService userServiceImpl = new UserServiceImpl();
            ProxyInvocationHander pih = new ProxyInvocationHander();
            pih.setUserService(userServiceImpl);
            UserService userService = (UserService)pih.getProxy();
            userService.add();
            userService.delte();
            userService.update();
            userService.selet();
        }
    }
    
  5. 测试结果

    使用了增加方法
    add方法使用成功
    使用了删除方法
    delte方法使用成功
    使用了修改方法
    update方法使用成功
    使用了查找方法
    selet方法使用成功
    

总结:在静态代理的基础上,每次添加一个真实角色,就需要一个对应的代理类来执行相应的代理操作。当使用动态代理类以后,不再拥有实际的代理类,而是使用真实角色的功能,即抽象角色(也就是接口),最终使用户能够控制所有的继承了这个接口的真实类。解决了静态代理的缺点,避免了代码的臃肿。


5、改良版的动态代理类模板

将所有的接口变成Object类,继而达到复用的效果

package pers.mobian.proxy.demo4;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyInvocationHander implements InvocationHandler {
    //被代理的接口
    private Object target;
    public void setUserService(Object target) {
        this.target = target;
    }

    //通过接口得到代理类
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    //对代理实例添加附属操作,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target, args);
        return result;
    }
}

标签:java,角色,void,代理,模式,proxy,public
From: https://blog.51cto.com/u_15942107/6017177

相关文章

  • 工厂模式+抽象工厂模式
    工厂模式1、概述核心实例化对象不使用new,用工厂方法代替将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦工厂模式满足的OOP原则:开闭原则......
  • 单例模式
    单例模式1、概述核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点常见场景:Window的任务管理器Window的回收站项目中,读取配置文件的类,一般......
  • 22.(行为型模式)java设计模式之备忘录模式
    一、什么是备忘录模式(MementoPattern)定义:在不破坏封闭的前提下,捕获⼀个对象的内部状态,保存对象的某个状态,以便在适当的时候恢复对象,⼜叫做快照模式,属于⾏为模式。备......
  • 04-代理模式
    04代理模式背景本博客是照着程杰的《大话设计模式》一书实现的Java代码的版本,再加自己的一点理解问题卓贾易追求娇娇的方式是派出自己的好友戴笠实现该模型的代码逻辑......
  • 读书笔记:价值投资.03.商业模式是什么
    商业模式是什么这个世界上有很多公司,靠商业模式赚钱.比如Uber,滴滴,几乎不拥有出租车,却是市场上最大的出租车公司.比如airbnb,几乎不拥有任何一家酒店,却是全球......
  • 设计模式之单例模式
    一、什么是单例模式?单例设计模式属于创建型模式范畴,所以主要用于处理对象创建和操作,当我们需要确保只创建一个特定类的实例,然后为整个应用程序提供对该实例的简单全局访问......
  • 设计模式——概览
     设计模式分二十三种,三大类,分别是:对象创建型抽象工厂、生成器、工厂方法、原型、单例结构型适配器、桥接、组合、装饰器、外观、享元、代理行为型责任链、......
  • 手写笔记22:代理模式
    ......
  • 18.(行为型模式)java设计模式之观察者模式
    一、什么是观察者模式定义对象间⼀种⼀对多的依赖关系,使得每当⼀个对象改变状态,则所有依赖于它的对象都会得到通知并⾃动更新,也叫做发布订阅模式Publish/Subscribe,属于⾏......
  • 学习模式-组合模式
    组合模式组合模式(CompositePattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的......