代理模式和装饰器模式

  • 代理模式:控制访问、权限、拦截(一对一)
  • 装饰器模式:动态叠加功能、层层包装(可多层)

一、代理模式(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 流、咖啡加料

一句话区分:

  • 代理:我替你干活,我管你能不能干
  • 装饰器:我包着你干活,我给你加功能
全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务