JAVA设计模式-代理模式
前言
回顾设计模式,让代码变得更加优雅
一、简介
代理模式(Proxy Pattern) 代理类代替目标对象执行功能,并且可以扩展目标对象的功能,又分为静态代理和动态代理
二、举例
设置一个薪酬计算器(目标对象,基本工资计算行为),分为员工薪酬计算器和高管薪酬计算器(代理对象),代理对象不仅能计算基本工资还扩展了其他薪酬体系计算行为
三、静态代理代码实现
/**
* @Author: 勇少
* @Date: 30/06/22 15:16
* @Description: 目标对象,提供计算基本工资行为
**/
public interface SalaryCalculator {
double calculate(int id);
}
public class SalaryCalculatorImpl implements SalaryCalculator{
@Override
public double calculate(int id) {
return 1000;
}
}
/**
* @Author: 勇少
* @Date: 30/06/22 15:19
* @Description: 代理对象
**/
public class OperationSalaryCalculator implements SalaryCalculator{
@Override
public double calculate(int id) {
System.out.println("补贴功能");
return 30000;
}
}
/**
* @Author: 勇少
* @Date: 30/06/22 15:19
* @Description: 代理对象暴露给外部调用
**/
public class Main {
public static void main(String[] args) {
SalaryCalculator operationSalary = new OperationSalaryCalculator(); //运营人员薪酬计算
double res = operationSalary.calculate(10);
System.out.println(res);
}
}
输出:
补贴功能
30000.0
优点
不同的代理类可以复用目标对象的方法,外部无法直接调用目标对象,代理对象无需考虑目标对象的具体实现
缺点
如果目标对象增加了其他的方法,那么所有的代理类也要相应的增加,代码维护复杂
四、JDK动态代理代码实现
/**
* @Author: 勇少
* @Date: 17/06/22 15:52
* @Description: 目标对象
**/
public interface SalaryCalculator {
double calculateSalary(int id);
}
/**
* @Author: 勇少
* @Date: 30/06/22 16:09
* @Description: 目标对象的业务实现
**/
public class SalaryCalculatorImpl implements SalaryCalculator {
@Override
public double calculateSalary(int id) {
return 10000;
}
}
/**
* @Author: 勇少
* @Date: 17/06/22 15:53
* @Description:
**/
public class SalaryLogProxy implements InvocationHandler {
private SalaryCalculator salaryCalculator;
public SalaryLogProxy(SalaryCalculator salaryCalculator) {
this.salaryCalculator = salaryCalculator;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("打印日志");
System.out.println("其他非目标对象拥有的功能");
return method.invoke(salaryCalculator, args);
}
}
/**
* @Author: 勇少
* @Date: 17/06/22 15:55
* @Description:
**/
public class Main {
public static void main(String[] args) {
SalaryCalculator salaryCalculator = new SalaryCalculatorImpl();
InvocationHandler handler = new SalaryLogProxy(salaryCalculator);
SalaryCalculator calculator = (SalaryCalculator)Proxy.newProxyInstance(SalaryCalculator.class.getClassLoader(), salaryCalculator.getClass().getInterfaces(), handler);
double v = calculator.calculateSalary(1);
System.out.println(v);
}
}
优点
- 不需要像静态代理那样在程序运行前新建对应的代理类
- 动态代理是在代码运行的时候创建的代理类,由JVN动态生成,可以代理多个目标对象
- 主要有Proxy负责生成动态代理类,其中它的newProxyInstance方法用来生成动态代理类实例
- InvocationHandler 接口只有invoke()一个方法,利用反射来调用被代理类的制定方法并返回结果。
缺点
- 基于反射,性能可能比较差
- 只能接口实现,不支持继承