Java學設計模式之裝飾器模式

Kllin發表於2024-05-09

一、模式概念

1.1 什麼是模式

裝飾模式是一種結構型設計模式,它允許向現有物件動態新增新功能,同時又不改變其結構。裝飾模式透過將物件放置在包裝器類中,然後在執行時動態地向物件新增新的行為或責任,從而實現這一目的。

結構

裝飾模式通常由以下幾個部分組成:

  1. Component(元件): 定義一個物件介面,可以動態地新增新的職責。
  2. ConcreteComponent(具體元件): 實現了元件介面,是被裝飾的物件。
  3. Decorator(裝飾器): 維持一個指向元件物件的引用,並實現與元件介面一致的介面。
  4. ConcreteDecorator(具體裝飾器): 負責給元件物件新增新的職責。

二、模式程式碼

2.1 元件

public interface Coffee {

    double cost();

    String getDescription();

}

2.2 具體元件

public class SimpleCoffee implements Coffee {
    @Override
    public double cost() {
        return 1.0;
    }

    @Override
    public String getDescription() {
        return "一杯咖啡";
    }
}

2.3 裝飾器

public abstract class CoffeeDecorator implements Coffee {

    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee decoratedCoffee) {
        this.decoratedCoffee = decoratedCoffee;
    }

    @Override
    public double cost() {
        return decoratedCoffee.cost();
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }
}

2.4 具體裝飾器

public class Milk extends CoffeeDecorator {
    public Milk(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    @Override
    public double cost() {
        return super.cost() + 0.5;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ",加牛奶";
    }
}
public class Sugar extends CoffeeDecorator {

    public Sugar(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }

    @Override
    public double cost() {
        return super.cost() + 0.2;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ",加糖";
    }
}

2.5 測試類

public class DecoratorPatternTest {
    public static void main(String[] args) {
        // 建立一個簡單的咖啡
        Coffee coffee = new SimpleCoffee();
        System.out.println("價格: " + coffee.cost() + ", 成分: " + coffee.getDescription());

        // 加入牛奶
        coffee = new Milk(coffee);
        System.out.println("價格: " + coffee.cost() + ", 成分: " + coffee.getDescription());

        // 再加入糖
        coffee = new Sugar(coffee);
        System.out.println("價格: " + coffee.cost() + ", 成分: " + coffee.getDescription());

        // 價格: 1.0, 成分: 一杯咖啡
        // 價格: 1.5, 成分: 一杯咖啡,加牛奶
        // 價格: 1.7, 成分: 一杯咖啡,加牛奶,加糖
    }
}

三、總結

裝飾模式的優點包括:

  • 可以動態地新增新的功能,而無需修改現有程式碼。
  • 可以避免使用大量的子類來擴充套件功能,使程式碼更加靈活和可維護。

缺點包括:

  • 可能會產生大量的具體裝飾器類,增加了類的數量和複雜度。
  • 裝飾器和元件之間的關係可能變得複雜,不易理解。

相關文章