摘要
本文介绍了装饰器设计模式,这是一种结构型设计模式,允许在不修改对象的情况下动态地为其添加功能。文章概述了装饰器模式的定义、作用、优点、缺点、类图实现和使用场景,强调了其在功能拓展、动态行为改变、避免类爆炸问题、增强现有对象功能、组合独立功能以及功能与行为解耦方面的优势。
1. 装饰器设计模式是什么
1.1. 装饰器设计模式
动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。
1.2. 装饰器设计模式作用
1.2.1. 装饰模式的优点:
- 使用装饰模式来实现扩展比继承更加灵活,它可以在不需要创造更多子类的情况下,将对象的功能加以扩展。
- 可以动态地给一个对象附加更多的功能。
- 可以用不同的装饰器进行多重装饰,装饰的顺序不同,可能产生不同的效果。
- 装饰类和被装饰类可以独立发展,不会相互耦合;装饰模式相当于是继承的一个替代模式。
1.2.2. 装饰模式的缺点:
- 与继承相比,用装饰的方式拓展功能更加容易出错,排错也更困难。对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
2. 装饰器模式类图实现
上图中的 Component 是一个抽象类,代表具有某中功能(function)的组件,ComponentImplA 和 ComponentImplB 分别是其具体的实现子类。Decorator 是 Component 装饰器,里面有一个 Component 的对象 decorated,这就是被装饰的对象,装饰器可为被装饰对象添加额外的功能或行为(addBehavior)。DecoratorImplA 和 DecoratorImplB 分别是两个具体的装饰器(实现子类)。
这样一种模式很好地将装饰器与被装饰的对象进行解耦。
3. 装饰器模式使用场景
装饰器模式(Decorator Pattern)是结构型设计模式之一,它允许在不改变对象自身的情况下,动态地为对象添加额外的功能。这个模式通常用于以下几种场景:
3.1. 功能拓展
如果你希望在运行时对一个对象的功能进行扩展,而不想通过继承的方式增加多个子类,装饰器模式是非常合适的。它可以在不影响原有类的情况下,通过多个装饰器逐步为对象添加功能。
示例场景:假设你有一个“咖啡”类,提供基本的咖啡功能。通过装饰器模式,你可以动态地添加不同的配料(比如牛奶、糖浆、奶油等),而不需要改变原始的“咖啡”类。每种配料可以是一个独立的装饰器类。
3.2. 动态改变对象行为
在一些系统中,可能需要根据不同的条件或需求来动态改变对象的行为,装饰器模式能够很好地支持这种需求。
示例场景:例如,在一个游戏中,不同的玩家可能会有不同的装备,装备带来不同的属性加成。你可以用装饰器来为玩家动态增加属性,而不需要为每种装备写一个独立的类。
3.3. 避免类爆炸问题
在某些情况下,通过继承来扩展功能会导致类的数量暴增,这时装饰器模式可以通过组合而不是继承来达到同样的目的,从而避免类层次过深。
示例场景:比如,一个支付系统可能有不同的支付方式,如银行卡支付、支付宝支付等,每种支付方式可能有不同的验证、支付记录等需求。如果使用继承,会产生大量的子类,而装饰器模式可以避免这一问题。你可以为每种支付方式添加验证、记录等功能,而不需要为每种功能分别创建子类。
3.4. 增强现有对象功能
如果你需要给一个已经存在的类增加一些额外的功能,但又不希望改变原类的实现或破坏现有的功能,可以使用装饰器模式。
示例场景:比如一个文件处理类,你可能想在它的基础上添加日志功能、缓存功能等,但又不希望修改原有的类结构。你可以创建不同的装饰器类,分别为文件处理类添加日志记录、缓存等功能。
3.5. 组合多个独立功能
装饰器模式允许多个装饰器独立地组合使用,这样可以根据需要灵活地添加、删除功能,而不需要修改原始对象或创建大量的子类。
示例场景:在一个用户认证系统中,你可以为用户添加多种认证方式(如密码认证、指纹认证、短信验证码等)。这些认证功能可以通过不同的装饰器来实现,用户的认证对象可以在运行时按需组合不同的认证方式。
3.6. 功能和行为的解耦
装饰器模式使得功能的增加与原始类解耦,不必修改原有的类逻辑。它实现了关注点分离,让功能的扩展和主类逻辑独立。
示例场景:假设你有一个日志系统,原始的系统类只负责核心业务,而日志功能可以作为一个装饰器来动态加入,这样日志和核心业务逻辑就被解耦开来。
4. 装饰器模式示例
4.1. 定义 Person
类
Person
是所有角色的基类,包含基本属性和方法。
public abstract class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void wear() {
System.out.println("我的着装是:");
}
}
4.2. 定义具体角色类
角色类 Engineer
和 Teacher
扩展自 Person
,并增加了各自的特殊属性和方法。
public class Engineer extends Person {
private String skill;
public Engineer(String name, String skill) {
super(name);
this.skill = skill;
}
public String getSkill() {
return skill;
}
@Override
public void wear() {
System.out.println("我是" + getSkill() + "工程师" + getName());
super.wear();
}
}
public class Teacher extends Person {
private String title;
public Teacher(String name, String title) {
super(name);
this.title = title;
}
public String getTitle() {
return title;
}
@Override
public void wear() {
System.out.println("我是" + getName() + getTitle());
super.wear();
}
}
4.3. 定义装饰器类
装饰器基类 ClothingDecorator
实现了装饰逻辑。
public abstract class ClothingDecorator extends Person {
protected Person decoratedPerson;
public ClothingDecorator(Person person) {
super(person.getName());
this.decoratedPerson = person;
}
@Override
public void wear() {
decoratedPerson.wear();
}
}
4.4. 定义具体装饰器
每个具体装饰器类负责装饰 Person
对象,扩展其 wear
方法。
public class CasualPantDecorator extends ClothingDecorator {
public CasualPantDecorator(Person person) {
super(person);
}
@Override
public void wear() {
super.wear();
System.out.println("一条卡其色休闲裤");
}
}
public class BeltDecorator extends ClothingDecorator {
public BeltDecorator(Person person) {
super(person);
}
@Override
public void wear() {
super.wear();
System.out.println("一条银色针扣头的黑色腰带");
}
}
public class LeatherShoesDecorator extends ClothingDecorator {
public LeatherShoesDecorator(Person person) {
super(person);
}
@Override
public void wear() {
super.wear();
System.out.println("一双深色休闲皮鞋");
}
}
public class KnittedSweaterDecorator extends ClothingDecorator {
public KnittedSweaterDecorator(Person person) {
super(person);
}
@Override
public void wear() {
super.wear();
System.out.println("一件紫红色针织毛衣");
}
}
public class WhiteShirtDecorator extends ClothingDecorator {
public WhiteShirtDecorator(Person person) {
super(person);
}
@Override
public void wear() {
super.wear();
System.out.println("一件白色衬衫");
}
}
public class GlassesDecorator extends ClothingDecorator {
public GlassesDecorator(Person person) {
super(person);
}
@Override
public void wear() {
super.wear();
System.out.println("一副方形黑框眼镜");
}
}
4.5. 测试
测试装饰器模式的效果。
public class DecoratorPatternTest {
public static void main(String[] args) {
// 创建基础对象
Person engineer = new Engineer("张三", "软件开发");
// 装饰对象
Person dressedEngineer = new GlassesDecorator(
new WhiteShirtDecorator(
new KnittedSweaterDecorator(
new CasualPantDecorator(
new BeltDecorator(
new LeatherShoesDecorator(engineer))))));
// 输出最终装扮
dressedEngineer.wear();
}
}
运行上述代码,输出结果如下:
复制代码
我是软件开发工程师张三
我的着装是:
一双深色休闲皮鞋
一条银色针扣头的黑色腰带
一条卡其色休闲裤
一件紫红色针织毛衣
一件白色衬衫
一副方形黑框眼镜
博文参考
《软件设计模式》