代理模式和装饰器模式
- 代理模式:控制访问、权限、拦截(一对一)
- 装饰器模式:动态叠加功能、层层包装(可多层)
一、代理模式(Proxy)完整示例
核心:接口不变,控制访问,增强逻辑,一对一
1. 共同接口
public interface UserService {
void save();
}
2. 真实对象
// 真正的业务类
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("执行保存用户操作");
}
}
3. 代理类(重点!)
// 代理类:控制访问、加权限、日志
public class UserServiceProxy implements UserService {
// 持有真实对象
private UserService target = new UserServiceImpl();
@Override
public void save() {
// 前置增强:权限控制
System.out.println("代理检查权限...");
// 调用真实对象
target.save();
// 后置增强
System.out.println("代理记录日志...");
}
}
4. 测试类
public class ProxyTest {
public static void main(String[] args) {
UserService service = new UserServiceProxy();
service.save();
}
}
运行结果
代理检查权限... 执行保存用户操作 代理记录日志...
二、装饰器模式(Decorator)完整示例
核心:接口不变,动态叠加功能,可多层嵌套
1. 共同接口
public interface Coffee {
String getDesc();
double cost();
}
2. 基础对象(被装饰者)
// 黑咖啡
public class BlackCoffee implements Coffee {
@Override
public String getDesc() {
return "黑咖啡";
}
@Override
public double cost() {
return 20.0;
}
}
3. 装饰器父类(持有被装饰对象)
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
4. 具体装饰器 1:加牛奶
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDesc() {
return coffee.getDesc() + " + 牛奶";
}
@Override
public double cost() {
return coffee.cost() + 5.0;
}
}
5. 具体装饰器 2:加糖
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDesc() {
return coffee.getDesc() + " + 糖";
}
@Override
public double cost() {
return coffee.cost() + 2.0;
}
}
6. 测试类(重点看多层装饰)
public class DecoratorTest {
public static void main(String[] args) {
// 基础咖啡
Coffee coffee = new BlackCoffee();
// 装饰:加牛奶
coffee = new MilkDecorator(coffee);
// 再装饰:加糖
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDesc());
System.out.println("价格:" + coffee.cost());
}
}
运行结果
黑咖啡 + 牛奶 + 糖 价格:27.0
三、代理 vs 装饰器 终极区别(面试必背)
目的 | 控制访问、权限、拦截 | 动态叠加功能、扩展 |
关系 | 一对一 | 一对多,可多层嵌套 |
创建对象 | 代理自己 new 真实对象 | 外部 传入被装饰对象 |
侧重点 | 能不能执行、权限检查 | 功能叠加、增强 |
典型场景 | Spring AOP、权限控制 | Java IO 流、咖啡加料 |
一句话区分:
- 代理:我替你干活,我管你能不能干
- 装饰器:我包着你干活,我给你加功能
查看6道真题和解析