Java 装饰器模式

前言

不知道是不是因为直译的缘故,很多Java技术或者说软工方面的术语都显得很书面化,初闻就给人一种很高大上的感觉,但事实上,其原理和应用场景都很易懂。

什么是装饰器模式

定义

在Java中,修饰器(Decorator)模式是一种结构型设计模式,它允许向对象添加新的功能,同时保持良好的封装性。这种模式通过创建包含被装饰对象的对象来工作,这样可以在运行时动态地给一个对象添加职责,而无需使用子类或者影响其他对象。

个人理解

书面化定义比较难以直观理解,而且一种有用的设计思想,总能提炼出很多适用场景,演化出很多适用的背景。就我的理解而言,装饰器模式的核心作用在于解决滥用继承的问题。
首先,继承是实现代码复用的一种强大方法,但除非超类是专门为扩展的目的而设计的,否则一旦父类的实现发生了改变,所有继承自它的子类都必须相应地调整,甚至父类一旦增加或修改方法,都可能使得子类产生安全问题。
其次,即使我们保证了超类是专门为扩展的目的而设计的,子类的数量控制也是一个问题,假设我们要给某个类加上三个基础功能,那么我们或许需要(2^3 - 1 = 7)个子类来覆盖所有可能的功能组合。
因而,在非必要情况下,与其扩展现有类,不如为新类提供一个引用现有类实例的私有字段。因为现有的类是新类的一个组件,新类中的实例方法仍然调用现有类实例的对应方法。

使用场景
  • 动态添加功能:在不修改对象的情况下,动态地给对象添加新的功能。
  • 替代继承:当继承层次结构过于复杂时,使用装饰器模式来替代继承,减少子类数量。
  • 组合功能:根据需要组合不同的功能,使对象具有多种特性。

装饰器模式的实现方式

组成部分
  1. Component(组件):定义一个对象接口,可以给这些对象动态地添加职责。比如说,饮料描述。
  2. Concrete Component(具体组件):定义一个对象,可以给它添加一些职责。比如说,具体到奶茶描述。
  3. Decorator(装饰器):持有Component类型的引用,并且定义一个与Component接口一致的接口。比如说,饮料加小料。
  4. Concrete Decorator(具体装饰器):负责给Component对象添加职责。比如说,奶茶加珍珠描述。
一个简单例子

完成一个不同饮品加多种小料的例子。
假设我们有一个Beverage接口,代表饮料的基本特性,比如获取描述和价格。

public interface Beverage {
    String getDescription();
    double cost();
}

然后定义几种具体的饮料实现这个接口:

public class MilkTea implements Beverage {
    @Override
    public String getDescription() {
        return "奶茶";
    }

    @Override
    public double cost() {
        return 5;
    }
}

接下来,定义一个装饰器接口,它继承自Beverage接口:

public abstract class CondimentDecorator implements Beverage {//加料
    @Override
    public abstract String getDescription();
}

然后定义具体的装饰器类,比如添加pearl的装饰器:

public class Pearl extends CondimentDecorator {
    private Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", 珍珠";
    }

    @Override
    public double cost() {
        return 3 + beverage.cost();
    }
}

最后,使用这些类:

public class Main {
    public static void main(String[] args) {
        Beverage beverage = new MilkTea();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());

        // 添加装饰器
        beverage = new Pearl(beverage);
        System.out.println(beverage.getDescription() + " $" + beverage.cost());
    }
}

注意事项

  • 过度使用装饰器模式会导致层次过于复杂。
  • 应该明确设计目的,避免随意添加装饰器。
装饰器模式是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。在装饰器模式中,这些封装对象称为装饰器。 在 Java 中,装饰器模式通常用于动态地修改对象的运行时行为,而不是在编译时就静态地修改代码。这种模式可以让你在不改变一个对象的前提下给其增加新的功能。 具体实现时,装饰器类和被装饰类通常都实现同一个接口或继承同一个父类,这样可以保证它们之间的互换性。 下面是一个简单的示例代码: ```java interface Component { void operation(); } class ConcreteComponent implements Component { public void operation() { System.out.println("ConcreteComponent.operation()"); } } class Decorator implements Component { private Component component; public Decorator(Component component) { this.component = component; } public void operation() { component.operation(); } } class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component component) { super(component); } public void operation() { super.operation(); System.out.println("ConcreteDecoratorA.operation()"); } } class ConcreteDecoratorB extends Decorator { public ConcreteDecoratorB(Component component) { super(component); } public void operation() { super.operation(); System.out.println("ConcreteDecoratorB.operation()"); } } public class Main { public static void main(String[] args) { Component component = new ConcreteComponent(); component = new ConcreteDecoratorA(component); component = new ConcreteDecoratorB(component); component.operation(); } } ``` 输出结果为: ``` ConcreteComponent.operation() ConcreteDecoratorA.operation() ConcreteDecoratorB.operation() ``` 这个示例中,`Component` 接口定义了一个 `operation()` 方法,`ConcreteComponent` 类实现了这个接口并提供了具体的实现。`Decorator` 类也实现了 `Component` 接口,并在其构造函数中接收一个 `Component` 对象,它的 `operation()` 方法会调用被装饰对象的 `operation()` 方法。`ConcreteDecoratorA` 和 `ConcreteDecoratorB` 类都继承自 `Decorator` 类,并在其 `operation()` 方法中先调用父类的 `operation()` 方法,再添加自己的行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值