一天一个设计模式:装饰者模式
概念:
装饰者模式又称为包装(wrapper)模式。装饰者模式对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
结构:
装饰者模式以透明的方式给一个对象附加上更多的责任,换而言之,客户端并不会觉得对象在装饰前后有什么不同,装饰者模式可以在不使用创造更多子类的情况下,将对象的功能拓展。
结构图:
角色分析:
抽象构件(Component)角色:给出一个抽象接口,以规范准备接受附加责任的对象。
具体构件(ConCreteComponent)角色:定义一个将要接受附加责任的类。
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。
代码:
抽象构建角色:

public interface Component {
public void sampleOperation();
}
具体构件角色:

public class ConcreteComponent implements Component {
@Override
public void sampleOperation() {
// 写相关的业务代码
}
}
装饰者角色:

public class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void sampleOperation() {
// 委派给构件
component.sampleOperation();
}
}
具体装饰者角色:
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void sampleOperation() {
super.sampleOperation();
// 写相关的业务代码
}
}
//B组件类似
具体示例
有工人接口,我们定义了铁匠,现在要对铁匠进行不同的技能强化。
工人接口:

public interface Worker {
void working();
}
铁匠实现类:

public class Smith implements Worker {
private String name;
private int age;
public Smith(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public void working() {
System.out.println("我是一个铁匠");
}
}
技能实现类:

public class Skill implements Worker { private Worker worker; public Skill(Worker worker) { this.worker = worker; } @Override public void working() { worker.working(); } //为半透明模式做的拓展 public void heating(){} }
具体的技能类1:

public class Hardening extends Skill {
public Hardening(Worker worker) {
super(worker);
}
@Override
public void working() {
System.out.println("我在淬火");
}
}
具体的技能类2:

public class Beat extends Skill {
public Beat(Worker worker) {
super(worker);
}
@Override
public void working() {
System.out.println("我在反复地捶打");
}
}
补充:
装饰者模式的简化
1.去掉接口的形式,直接继承自要被装饰的类即可。
2.直接使用实现接口的形式实现装饰,而不用再额外加一层继承关系。适用于只有一个强化关系的情况
透明度的要求:
装饰者模式要求程序不应该声明需要被装饰的实体类,而是应该声明抽象接口。
用示例中的声明表示就是下面这样:
即所有的人,都是工人,铁匠是工人,会淬火的铁匠也是工人。

Worker worker1 = new Smith("李铁蛋",18); Worker worker2 = new Hardening(worker1);
半透明的装饰模式:
当发现工人接口并不能满足所有的要求的时候,要想实现透明度要求,必须在接口中添加新方法,所以很多实现的装饰者模式都是采取“半透明”的方式,即装饰者类可以对接口进行拓展,同时声明的时候,可以选择以装饰者类为准。
本例中,装饰者类就是技能类,我们为淬火技能类添加加热方法

Worker worker = new Smith("李狗蛋",18); Hardening smith = new Hardening(worker); smith.heating();
半透明的装饰者模式是介于装饰者模式跟适配器模式中的,适配器模式的思路是改变接口,也可以通过改写或新增方法实现,大多数装饰者模式实际上都是半透明的装饰者模式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!