Loading... # 装饰模式 装饰模式(Decorator Pattern)是结构型设计模式之一。它通过创建一个装饰类来包装原始类,从而在不改变原始类代码的情况下,动态地添加职责(功能)到对象。装饰模式提供了一种灵活的替代继承的方式,扩展对象的功能。 ### 定义 #### 定义和意图 装饰模式的定义是:动态地将职责附加到对象上。装饰模式通过创建一个装饰类,将原始类的功能包装在其中,以便可以在不修改原始类的情况下扩展其功能。其主要意图是解决类的扩展问题,避免了继承方式的缺陷。 #### 使用场景 装饰模式适用于以下几种场景: * **需要扩展一个类的功能**:但不希望通过创建子类的方法来实现。 * **动态添加功能**:需要在运行时动态地添加或撤销功能。 * **功能的组合**:通过组合不同的装饰对象来获得多种功能组合。 ### 结构 #### 角色和职责 1. **组件接口(Component)** :定义一个对象接口,可以给这些对象动态地添加职责。 2. **具体组件(Concrete Component)** :实现组件接口的类,表示被装饰的原始对象。 3. **装饰器(Decorator)** :持有一个组件对象的引用,并实现组件接口,基类装饰器通常是抽象类。 4. **具体装饰器(Concrete Decorator)** :实现装饰器类,负责向被装饰的对象添加职责。 ### 实现 #### 示例场景一:文本处理系统 假设我们有一个基本的文本处理系统,可以对文本进行读取和显示。我们希望在不修改现有代码的情况下,动态地添加文本的装饰功能,例如加粗、斜体和下划线等。 #### UML类图 ```plantuml @startuml interface TextComponent { +display() } class PlainText implements TextComponent { +PlainText(text: String) +display() } abstract class TextDecorator implements TextComponent { -component: TextComponent +TextDecorator(component: TextComponent) +display() } class BoldTextDecorator extends TextDecorator { +BoldTextDecorator(component: TextComponent) +display() } class ItalicTextDecorator extends TextDecorator { +ItalicTextDecorator(component: TextComponent) +display() } class UnderlineTextDecorator extends TextDecorator { +UnderlineTextDecorator(component: TextComponent) +display() } TextComponent <|.. PlainText TextComponent <|.. TextDecorator TextDecorator <|-- BoldTextDecorator TextDecorator <|-- ItalicTextDecorator TextDecorator <|-- UnderlineTextDecorator TextDecorator o-- TextComponent @enduml ``` #### Java代码示例 ```java // 组件接口,定义基本操作 interface TextComponent { void display(); } // 具体组件,实现文本显示 class PlainText implements TextComponent { private String text; public PlainText(String text) { this.text = text; } @Override public void display() { System.out.print(text); } } // 装饰器抽象类,持有一个TextComponent对象的引用 abstract class TextDecorator implements TextComponent { protected TextComponent component; public TextDecorator(TextComponent component) { this.component = component; } @Override public void display() { component.display(); } } // 具体装饰器,实现加粗功能 class BoldTextDecorator extends TextDecorator { public BoldTextDecorator(TextComponent component) { super(component); } @Override public void display() { System.out.print("**"); super.display(); System.out.print("**"); } } // 具体装饰器,实现斜体功能 class ItalicTextDecorator extends TextDecorator { public ItalicTextDecorator(TextComponent component) { super(component); } @Override public void display() { System.out.print("_"); super.display(); System.out.print("_"); } } // 具体装饰器,实现下划线功能 class UnderlineTextDecorator extends TextDecorator { public UnderlineTextDecorator(TextComponent component) { super(component); } @Override public void display() { System.out.print("~"); super.display(); System.out.print("~"); } } // 客户端代码 public class DecoratorPatternDemo1 { public static void main(String[] args) { // 原始文本 TextComponent plainText = new PlainText("Hello, World!"); // 加粗文本 TextComponent boldText = new BoldTextDecorator(plainText); boldText.display(); // 输出:**Hello, World!** System.out.println(); // 加粗斜体文本 TextComponent boldItalicText = new BoldTextDecorator(new ItalicTextDecorator(plainText)); boldItalicText.display(); // 输出:**_Hello, World!_** System.out.println(); // 加粗斜体下划线文本 TextComponent fullDecoratedText = new BoldTextDecorator(new ItalicTextDecorator(new UnderlineTextDecorator(plainText))); fullDecoratedText.display(); // 输出:**_~Hello, World!~_** } } ``` #### 详细解释 在这个示例中,`TextComponent`接口定义了文本显示的方法`display`。`PlainText`类实现了该接口,并提供了基本的文本显示功能。`TextDecorator`是一个抽象类,持有一个`TextComponent`对象,并实现了`TextComponent`接口。具体装饰器类`BoldTextDecorator`、`ItalicTextDecorator`和`UnderlineTextDecorator`分别实现了加粗、斜体和下划线的功能。 通过这种方式,我们可以在不修改`PlainText`类的情况下,动态地为文本添加多种装饰功能。 #### 示例场景二:咖啡店订单系统 假设我们有一个基本的咖啡店订单系统,可以对咖啡进行订购。我们希望在不修改现有代码的情况下,动态地添加咖啡的装饰功能,例如添加牛奶、糖和香草等。 #### UML类图 ```plantuml @startuml interface Coffee { +getDescription(): String +getCost(): double } class SimpleCoffee implements Coffee { +getDescription(): String +getCost(): double } abstract class CoffeeDecorator implements Coffee { -coffee: Coffee +CoffeeDecorator(coffee: Coffee) +getDescription(): String +getCost(): double } class MilkDecorator extends CoffeeDecorator { +MilkDecorator(coffee: Coffee) +getDescription(): String +getCost(): double } class SugarDecorator extends CoffeeDecorator { +SugarDecorator(coffee: Coffee) +getDescription(): String +getCost(): double } class VanillaDecorator extends CoffeeDecorator { +VanillaDecorator(coffee: Coffee) +getDescription(): String +getCost(): double } Coffee <|.. SimpleCoffee Coffee <|.. CoffeeDecorator CoffeeDecorator <|-- MilkDecorator CoffeeDecorator <|-- SugarDecorator CoffeeDecorator <|-- VanillaDecorator CoffeeDecorator o-- Coffee @enduml ``` #### Java代码示例 ```java // 组件接口,定义基本操作 interface Coffee { String getDescription(); double getCost(); } // 具体组件,实现基本咖啡 class SimpleCoffee implements Coffee { @Override public String getDescription() { return "Simple Coffee"; } @Override public double getCost() { return 5.0; } } // 装饰器抽象类,持有一个Coffee对象的引用 abstract class CoffeeDecorator implements Coffee { protected Coffee coffee; public CoffeeDecorator(Coffee coffee) { this.coffee = coffee; } @Override public String getDescription() { return coffee.getDescription(); } @Override public double getCost() { return coffee.getCost(); } } // 具体装饰器,实现添加牛奶功能 class MilkDecorator extends CoffeeDecorator { public MilkDecorator(Coffee coffee) { super(coffee); } @Override public String getDescription() { return coffee.getDescription() + ", Milk"; } @Override public double getCost() { return coffee.getCost() + 1.5; } } // 具体装饰器,实现添加糖功能 class SugarDecorator extends CoffeeDecorator { public SugarDecorator(Coffee coffee) { super(coffee); } @Override public String getDescription() { return coffee.getDescription() + ", Sugar"; } @Override public double getCost() { return coffee.getCost() + 0.5; } } // 具体装饰器,实现添加香草功能 class VanillaDecorator extends CoffeeDecorator { public VanillaDecorator(Coffee coffee) { super(coffee); } @Override public String getDescription() { return coffee.getDescription() + ", Vanilla"; } @Override public double getCost() { return coffee.getCost() + 2.0; } } // 客户端代码 public class DecoratorPatternDemo2 { public static void main(String[] args) { // 基本咖啡 Coffee simpleCoffee = new SimpleCoffee(); System.out.println(simpleCoffee.getDescription() + " $" + simpleCoffee.getCost()); // 添加牛奶的咖啡 Coffee milkCoffee = new MilkDecorator(simpleCoffee); System.out.println(milkCoffee.getDescription() + " $" + milkCoffee.getCost()); // 添加牛奶和糖的咖啡 Coffee milkSugarCoffee = new MilkDecorator(new SugarDecorator(simpleCoffee)); System.out.println(milkSugarCoffee.getDescription() + " $" + milkSugarCoffee.getCost()); // 添加牛奶、糖和香草的咖啡 Coffee fullyDecoratedCoffee = new MilkDecorator(new SugarDecorator(new VanillaDecorator(simpleCoffee))); System.out.println(fullyDecoratedCoffee.getDescription() + " $" + fullyDecoratedCoffee.getCost()); } } ``` #### 详细解释 在这个示例中,`Coffee`接口定义了咖啡的基本操作,包括获取描述和价格。`SimpleCoffee`类实现了该接口,提供了基本的咖啡功能。`CoffeeDecorator`是一个抽象类,持有一个`Coffee`对象,并实现了`Coffee`接口。具体装饰器类`MilkDecorator`、`SugarDecorator`和`VanillaDecorator`分别实现了添加牛奶、糖和香草的功能。 通过这种方式,我们可以在不修改`SimpleCoffee`类的情况下,动态地为咖啡添加多种装饰功能。 #### 示例场景三:图形绘制系统 假设我们有一个基本的图形绘制系统,可以绘制基本的图形。我们希望在不修改现有代码的情况下,动态地添加图形的装饰功能,例如边框、阴影和颜色等。 #### UML类图 ```plantuml @startuml interface Shape { +draw() } class Circle implements Shape { +draw() } class Rectangle implements Shape { +draw() } abstract class ShapeDecorator implements Shape { -shape: Shape +ShapeDecorator(shape: Shape) +draw() } class BorderDecorator extends ShapeDecorator { +BorderDecorator(shape: Shape) +draw() } class ShadowDecorator extends ShapeDecorator { +ShadowDecorator(shape: Shape) +draw() } class ColorDecorator extends ShapeDecorator { +ColorDecorator(shape: Shape, color: String) +draw() -setColor(shape: Shape, color: String) } Shape <|.. Circle Shape <|.. Rectangle Shape <|.. ShapeDecorator ShapeDecorator <|-- BorderDecorator ShapeDecorator <|-- ShadowDecorator ShapeDecorator <|-- ColorDecorator ShapeDecorator o-- Shape @enduml ``` #### Java代码示例 ```java // 组件接口,定义基本操作 interface Shape { void draw(); } // 具体组件,实现基本图形 class Circle implements Shape { @Override public void draw() { System.out.println("Drawing a Circle"); } } class Rectangle implements Shape { @Override public void draw() { System.out.println("Drawing a Rectangle"); } } // 装饰器抽象类,持有一个Shape对象的引用 abstract class ShapeDecorator implements Shape { protected Shape shape; public ShapeDecorator(Shape shape) { this.shape = shape; } @Override public void draw() { shape.draw(); } } // 具体装饰器,实现添加边框功能 class BorderDecorator extends ShapeDecorator { public BorderDecorator(Shape shape) { super(shape); } @Override public void draw() { shape.draw(); setBorder(shape); } private void setBorder(Shape shape) { System.out.println("Adding a Border"); } } // 具体装饰器,实现添加阴影功能 class ShadowDecorator extends ShapeDecorator { public ShadowDecorator(Shape shape) { super(shape); } @Override public void draw() { shape.draw(); setShadow(shape); } private void setShadow(Shape shape) { System.out.println("Adding a Shadow"); } } // 具体装饰器,实现添加颜色功能 class ColorDecorator extends ShapeDecorator { private String color; public ColorDecorator(Shape shape, String color) { super(shape); this.color = color; } @Override public void draw() { shape.draw(); setColor(shape, color); } private void setColor(Shape shape, String color) { System.out.println("Adding color: " + color); } } // 客户端代码 public class DecoratorPatternDemo3 { public static void main(String[] args) { // 基本圆形 Shape circle = new Circle(); // 添加边框的圆形 Shape borderCircle = new BorderDecorator(circle); borderCircle.draw(); System.out.println(); // 添加边框和阴影的矩形 Shape borderShadowRectangle = new BorderDecorator(new ShadowDecorator(new Rectangle())); borderShadowRectangle.draw(); System.out.println(); // 添加边框、阴影和颜色的圆形 Shape fullyDecoratedCircle = new BorderDecorator(new ShadowDecorator(new ColorDecorator(circle, "Red"))); fullyDecoratedCircle.draw(); } } ``` #### 详细解释 在这个示例中,`Shape`接口定义了图形的基本操作`draw`。`Circle`和`Rectangle`类实现了该接口,提供了基本的图形绘制功能。`ShapeDecorator`是一个抽象类,持有一个`Shape`对象,并实现了`Shape`接口。具体装饰器类`BorderDecorator`、`ShadowDecorator`和`ColorDecorator`分别实现了添加边框、阴影和颜色的功能。 通过这种方式,我们可以在不修改`Circle`和`Rectangle`类的情况下,动态地为图形添加多种装饰功能。 ### 优缺点 #### 优点 * **动态扩展对象功能**:在不修改原始类代码的情况下,动态地扩展对象的功能。 * **灵活性高**:通过组合不同的装饰器对象,可以实现多种功能组合。 * **遵循开闭原则**:通过引入装饰器类,可以在不修改原始类的情况下扩展功能。 #### 缺点 * **增加系统复杂性**:可能会增加大量的装饰器类,导致系统复杂性增加。 * **性能开销**:由于使用了多层装饰器,可能会导致性能开销。 ### 实际应用 #### 真实案例 装饰器模式在实际开发中应用广泛。例如,Java的I/O流库使用了装饰器模式,通过装饰器类(如`BufferedInputStream`、`DataInputStream`等)为基本的I/O流(如`FileInputStream`)动态地添加功能。 #### 应用场景讨论 装饰器模式适合用于以下场景: * **动态添加功能**:需要在运行时动态地添加或撤销功能。 * **功能的组合**:通过组合不同的装饰器对象,动态地为对象添加多种功能。 * **扩展类功能**:需要扩展一个类的功能,但不希望通过创建子类的方法来实现。 ### 总结 装饰器模式通过创建一个装饰类来包装原始类,从而在不改变原始类代码的情况下,动态地添加职责到对象。学习和应用这一模式,可以帮助开发者设计出更加灵活、可扩展的代码。在实际应用中,我们应根据具体需求选择合适的设计模式,并结合其他模式共同使用,以达到最佳效果。 最后修改:2024 年 07 月 04 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果文章有帮助到你,请随意赞赏
1 条评论
建议融入东方智慧,形成对话张力。