Java 设计模式之代理模式

代理模式:为其他对象提供一种代理以控制对这个对象的访问
一、静态代理:
UML 图
1. 抽象角色,基于面向对象的思想,首先定义一个俱乐部接口,它有一个实现球员需求的方法。
public interface IClub {
    public void getSalary(String salary);
}

2. 真实角色,球员自己和俱乐部谈薪水

public class Player implements IClub {
    private String name;
    public Player(String name) {
        this.name = name;
    }
    @Override
    public void getSalary(String salary) {
        System.out.println("球员:" + name + ",周薪:" + salary);
    }
}
3. 代理角色,球员经纪人和俱乐部谈薪水
public class Agent implements IClub {
    private IClub club;
    
    public Agent(IClub club){
        this.club=club;
    }
    
    @Override
    public void getSalary(String slary) {
        club.getSalary(slary);
    }  
}

4. 客户端

public class ProxyClient {
    public static void main(String[] args) {
        // 定义一个球员
        IClub meixi = new Player("梅西");
        // 定义一个经纪人
        Agent meixiAgent = new Agent(meixi);
        // 通过经纪人和俱乐部来谈薪水
        meixiAgent.getSalary("梅西周薪40英镑");
    }
}
结果:
球员 :梅西,周薪:梅西周薪40英镑
通过上面一个接口,两个实现类,就完成了静态代理模式。经纪人充当球员代理人得角色,球员把需求告诉经纪人,并不需要和俱乐部进行沟通。同时经纪人不只是执行谈薪水这一个工作,还可做其他业务逻辑处理,例如:
if (salary.equals("周薪10万英镑")) {
            System.out.println("工资偏低哦!");
        } else if (salary.equals("周薪100万英镑")) {
            System.out.println("你是要抢吗!");
        } else {
            club.getSalary(salary);
        }
总结:
代理模式包含如下角色:
  • Subject : 抽象主题角色。可以是接口,也可以是抽象类。
  • RealSubject : 真实主题角色。业务逻辑的具体执行者。
  • ProxySubject : 代理主题角色。内部含有RealSubject的引用(关联关系),负责对真实角色的调用,并在真实主题角色处理前后做预处理和善后工作。
代理模式优点:
  • 职责清晰 真实角色只需关注业务逻辑的实现,非业务逻辑部分,后期通过代理类完成即可。
  • 高扩展性 不管真实角色如何变化,由于接口是固定的,代理类无需做任何改动。

二、动态代理

与静态代理相比,抽象角色、真实角色都没有变化。变化的只有代理类。因此,抽象角色、真实角色,参考IClub和Player。
1. 中介类
/**
* 需求:在谈薪水的前后加上当前时间 定义一个位于代理类与委托类之间的中介类,也叫动态代理类,这个类被要求实现InvocationHandler接口
* 当我们调用代理类对象的方法时,这个“调用”会转送到中介类的invoke方法中,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。
*/
public class AgentDynamic implements InvocationHandler {
    // 被代理的实例
    private IClub club;
    public AgentDynamic(IClub club) {
        this.club = club;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("谈薪水之前的时间:" + System.currentTimeMillis());
        Object result = method.invoke(club, args);
        System.out.println("谈薪水之后的时间:" + System.currentTimeMillis());
        return result;
    }
}

2. 客户端

public class DynamicProxyClient {
    public static void main(String[] args) {
        // 定义一个球员
        IClub meixi = new Player("梅西");
        // 创建一个中介动态代理对象
        InvocationHandler agentDynamic = new AgentDynamic(meixi);
        // 获取类加载器
        ClassLoader classLoader = meixi.getClass().getClassLoader();
        // 动态产生一个代理类
        IClub proxy = (IClub) Proxy.newProxyInstance(classLoader, meixi.getClass().getInterfaces(), agentDynamic);
        // 通过经纪人和俱乐部来谈薪水
        proxy.getSalary("梅西周薪40英镑");
    }
总结:
动态代理中,代理类并不是在Java代码中实现,而是在运行时期生成,相比静态代理,动态代理可以很方便的对委托类的方法进行统一处理,如添加方法调用次数、添加日志、事务控制功能等等,动态代理分为jdk动态代理和cglib动态代理。
一个典型的动态代理可分为以下四个步骤:
  1. 创建抽象角色
  2. 创建真实角色
  3. 通过实现InvocationHandler接口创建中介类
  4. 通过场景类,动态生成代理类
个人理解:
  1. 为什么要用代理模式? 使用代理模式就是类似于找中介或者明星找经纪人,我们需要找房子,可以通过中介帮我找,跟中介说我们的需求,中介找好了(封装)我们直接入住就行。
  2. 那为什么需要用动态代理?接着上面说,每个人找房子要求不一样,但是大家都有一个目标,房子必须得有卫生间对吧,这个时候每个人都跟中介说我的房子需要卫生间(名字+卫生间)吗?不对,这时候我们应该统一的在一个类中加以说明(不修改源码的情况下做增强)就可以,于是就有了动态代理。
以下摘自网络
    1. Proxy类(AgentDynamic 类)的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
    2. 可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
    3. 解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。

版权声明:本文为博主原创文章,未经博主允许不得转载。 

猜你喜欢

转载自www.cnblogs.com/hellovoyager1/p/9155811.html