代理模式和装饰器模式

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

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

一句话区分:

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

相关推荐

工作职责 1、根据需求完成数据平台相关系统的前端开发与迭代,覆盖 Web 场景,移动端以响应式适配为主;2、在现有技术栈与规范下实现页面与交互,复用组件库与设计系统,保证交付质量与一致性;3、配合后端完成接口联调与问题排查,按期交付需求、修复缺陷并进行回归验证;4、基于常用图表库实现数据可视化,完成报表、看板和简单的交互分析;在指导下进行基础性能优化;5、遵循工程规范(代码风格、Git 流程、提交规范),参与代码评审与文档补充。任职要求1、2027届及之后毕业的在校生,本科及以上学历,计算机相关专业;2、熟练掌握 JavaScript/TypeScript 与 HTML/CSS,至少熟悉 Vue 或 React 其中一种,能独立完成中后台页面开发;3、熟悉常见前端工程化工具与包管理(Vite/Webpack、NPM/Yarn/Pnpm),会使用常见脚手架;4、能阅读 PRD/原型并快速还原设计,注重交互一致性与可用性;5、具备数据可视化开发经验,能使用 ECharts/AntV/G2Plot 等实现常见图表与图表联动;6、良好的沟通协作与时间管理能力,能按里程碑交付、响应问题并持续优化。面向对象2027届及之后毕业的在校生投递链接https://jobs.mihoyo.com/?sharePageId=121176&recommendationCode=052BT&isRecommendation=true#/campus/position/8148
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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