在面向对象程序设计中,装饰者模式是一种结构型模式,它允许动态地将新功能添加到对象中,通常通过将对象包装在具有新行为的装饰类中来实现。Java装饰者设计模式是一种为Java语言特定的实现。
Java装饰者模式背景
装饰者模式有时被称为“包装器模式”,它使开发人员能够通过将新行为“包装”到对象中而动态地扩展该对象的功能,而不必所涉及的任何类进行修改。使用装饰者模式时,应用程序可以在运行时添加行为,而不必依赖于继承或修改底层代码。这种模式使得在扩展类的功能方面更加灵活。
Java装饰者模式实现
Java装饰者模式的实现往往涉及一个抽象基类,该类定义了要装饰的对象的“抽象接口”(也称为“组件”)。装饰器类则扩展该基类,并将子类包含在其中示意图。
##### UML类图
```
---------------
| Component |
---------------
/\
|
-------------------
| ConcreteComponent |
-------------------
/\
|
--------------
| Decorator |
--------------
/\
|
--------------------
| ConcreteDecorator |
--------------------
```
在Java中,可以使用抽象类或接口创建抽象基类。具体基类是实现基类的一种类。装饰器类是抽象基类的扩展,它可以将其他对象包装到其中。具体装饰器类从装饰器类派生而来,这些类可能会增加它们所包含的对象的新功能。
Java装饰者模式示例
下面是一个简单的示例,其中Order接口描述点了咖啡的客户订单。Coffee类是Order接口的一个具体实现:它表示一杯咖啡。
```
public interface Order {
public double getCost();
public String getDescription();
}
public class Coffee implements Order {
public double getCost() {
return 1.99;
}
public String getDescription() {
return "Coffee";
}
}
```
现在,我们可以创建Decorator抽象基类来表示添加任何东西的基本咖啡。比如Sugar、Milk、Whip等等。不同于咖啡的具体实现,装饰器没有自己的描述或成本:它们相当于“空集合”,只是用来装饰具体实现的。
```
public abstract class CoffeeDecorator implements Order {
protected final Order decoratedCoffee;
protected String ingredientSeparator = ", ";
public CoffeeDecorator(Order decoratedCoffee) {
this.decoratedCoffee = decoratedCoffee;
}
public double getCost() { //计算所有装饰的成本
return decoratedCoffee.getCost();
}
public String getDescription() { //添加所有装饰的描述
return decoratedCoffee.getDescription()
+ ingredientSeparator
+ getAddedDescription();
}
protected abstract String getAddedDescription();
}
```
现在,我们可以创建具体Decorator的不同实现,比如Sugar、Milk、Whip等等。每一种装饰都覆盖了getAddedDescription方法,添加了新的描述。注意,每一个具体装饰都委派到它所包含的咖啡。
```
public class Sugar extends CoffeeDecorator {
public Sugar(Order decoratedCoffee) {
super(decoratedCoffee);
}
protected String getAddedDescription() {
return "Sugar";
}
public double getCost() {
return super.getCost() + 0.15;
}
}
public class Milk extends CoffeeDecorator {
public Milk(Order decoratedCoffee) {
super(decoratedCoffee);
}
protected String getAddedDescription() {
return "Milk";
}
public double getCost() {
return super.getCost() + 0.25;
}
}
public class Whip extends CoffeeDecorator {
public Whip(Order decoratedCoffee) {
super(decoratedCoffee);
}
protected String getAddedDescription() {
return "Whip";
}
public double getCost() {
return super.getCost() + 0.10;
}
}
```
Java装饰者模式的优缺点
Java装饰者设计模式的优点:
- 无需修改现有代码即可在运行时添加新功能。
- 可以将新功能动态地包装到对象中。
- 允许在不破坏类层次结构的情况下扩展功能。
Java装饰者设计模式的缺点:
- 可能会导致对象数量爆炸。
Java装饰者模式和适配器模式的区别
Java装饰者模式和适配器模式都属于结构型模式,它们都涉及到将对象包装在另一个对象中。但是,这两种模式有以下不同点:
适配器模式:
- 目的是使不兼容的对象能够相互工作。
- 通过继承或对象组合将对象包装在包装器中。
- 没有修改现有代码,但在许多情况下,需要创建一个特定于应用程序的适配器。
装饰者模式:
- 目的是动态地添加新功能或行为。
- 通过实现相同的接口和继承来装饰对象。
- 允许在运行时添加新功能,而不必依靠底层代码。
Java装饰者设计模式应用场景
Java装饰者设计模式适用于以下情况:
- 可以在运行时添加和删除对象的功能。
- 必须向多个对象添加功能,且必须禁用某些功能。
- 在不影响其他对象的情况下添加或删除对象的功能。
结语
Java装饰者模式是一种灵活的设计模式,它允许动态地添加行为和功能。它的优点是很大的灵活性,可以在不影响代码的情况下添加新功能。使用Java装饰者模式可以避免继承的局限性,从而实现更好的缩放和灵活性。Java装饰者模式的三个关键词是:动态、构建、组合。
扫码咨询 领取资料