引言
在刚开始承接需求的时候,大多数的开发者都采用了一种平铺式的开发思路,从头到尾,一个方法就将需求实现啦,简单又快捷。殊不知后续的维护成为了头疼的事情,真是开发一时爽,后续维护火葬场。新增需求就成为打补丁的工作,慢慢的就成了人们常说的s山代码。
作为有点追求的开发者来说,提高自身面向对象编程的能力成为了补强的一个点。其中设计模式对于改造代码结构起着非常重要的作用,并且主流框架里面也很多地方采用了设计模式的地方,因此熟悉设计模式,对于自己的需求实现还是理解其他项目也起着非常重要的作用。今天来记录一下另一个简单的设计模式-装饰器设计模式(Decorator Pattern)。
装饰器设计模式(Decorator Pattern)
装饰器设计模式属于结构型设计模式。它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式使得你可以动态地给一个对象添加一些额外的职责。其UML图如下:使用了装饰器模式来为咖啡添加额外的配料(如糖和牛奶),并计算添加配料后的总价格。
代码实例如下:
// 组件接口:饮料
interface Beverage{
String getDescription();
double getCost();
}
//具体组件 Coffee 类
class SimpleCoffee implements Beverage {
@Override
public String getDescription() {
return "Simple Coffee";
}
@Override
public double getCost() {
return 1.0;
}
}
// 装饰抽象类
abstract class CondimentDecorator implements Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage){
this.beverage = beverage;
}
}
class Sugar extends CondimentDecorator {
public Sugar(Beverage beverage){
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Sugar";
}
@Override
public double getCost() {
return beverage.getCost() + 0.2;
}
}
class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
@Override
public double getCost() {
return beverage.getCost() + 0.5;
}
}
/**
* @堆代码 duidaima.com
* @date 2024/7/6 14:34
*/
public class Main {
public static void main(String[] args) {
SimpleCoffee simpleCoffee = new SimpleCoffee();
System.out.println(simpleCoffee.getDescription() + " $" + simpleCoffee.getCost());
Sugar sugar = new Sugar(simpleCoffee);
System.out.println(sugar.getDescription() + " $" + sugar.getCost());
Milk milk = new Milk(sugar);
System.out.println(milk.getDescription() + " $" + milk.getCost());
Milk milk1 = new Milk(milk);
System.out.println(milk1.getDescription() + " $" + milk1.getCost());
}
}
代码解析:
• Beverage 接口:这是组件接口,定义了所有饮料应该具有的行为,即 getDescription() 和 getCost() 方法。
• SimpleCoffee 类:实现了 Beverage 接口,表示最基础的咖啡,没有添加任何配料。它重写了 getDescription() 和 getCost() 方法。
• CondimentDecorator 抽象类:这是装饰器抽象类,继承自 Beverage 接口,用于给 Beverage 添加额外的责任。它包含了一个 Beverage 类型的成员变量 beverage,用于保存被装饰的对象。构造函数接收一个 Beverage 对象作为参数,并将其赋值给 beverage 成员变量。
• Sugar 和 Milk 类:这两个类是具体装饰器类,继承自 CondimentDecorator 抽象类,分别代表添加糖和牛奶的装饰器。它们都重写了 getDescription() 和 getCost() 方法,用于在原有饮料的基础上添加配料的描述和价格。
• Main 类中的 main 方法:在方法中分别创建了SimpleCoffee、Sugar、Milk对象,展示了如何通过多次装饰来动态地添加责任。
小结
相比于继承的方式,装饰器模式适用于需要在运行时动态地添加或移除功能的情况,而继承更适合那些在设计阶段就已经确定下来的功能扩展场景。