動態

詳情 返回 返回

Java 設計模式:裝飾者模式(Decorator Pattern) - 動態 詳情

一、模式定義

裝飾者模式屬於結構型設計模式,允許通過動態包裝對象的方式為對象添加新功能,提供比繼承更靈活的擴展方式。該模式通過組合替代繼承,遵循開閉原則(對擴展開放,對修改關閉)。

二、核心角色

  1. Component(組件接口)

    • 定義被裝飾對象的公共接口
  2. ConcreteComponent(具體組件)

    • 實現基礎功能的具體類
  3. Decorator(裝飾者基類)

    • 持有Component引用,實現Component接口
  4. ConcreteDecorator(具體裝飾者)

    • 添加具體裝飾功能的實現類

三、經典實現(咖啡店訂單系統)

// 1. 組件接口
public interface Coffee {
    String getDescription();
    double cost();
}

// 2. 具體組件
public class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "Simple Coffee";
    }

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

// 3. 裝飾者基類
public abstract class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;

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

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

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

// 4. 具體裝飾者
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

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

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

public class MochaDecorator extends CoffeeDecorator {
    public MochaDecorator(Coffee coffee) {
        super(coffee);
    }

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

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

// 5. 客户端使用
public class CoffeeShop {
    public static void main(String[] args) {
        Coffee order = new SimpleCoffee();
        System.out.println(order.getDescription() + " $" + order.cost());

        order = new MilkDecorator(order);
        System.out.println(order.getDescription() + " $" + order.cost());

        order = new MochaDecorator(order);
        System.out.println(order.getDescription() + " $" + order.cost());
    }
}

四、模式結構UML

           _________________________
          |        Component        |
          |-------------------------|
          | + getDescription()      |
          | + cost()                |
          |_________________________|
                     ▲
          ___________|___________
         |                       |
 _________▼_________       ______▼_______
| ConcreteComponent |     |   Decorator  |
|-------------------|     |--------------|
| + getDescription()|     | - component  |
| + cost()          |     |______________|
|___________________|              ▲
                           _________|_________
                          |                   |
                   _______▼_______     _______▼_______
                  | ConcreteDecoratorA |   | ConcreteDecoratorB |
                  |--------------------|   |--------------------|
                  | + addedBehavior()  |   | + addedBehavior()  |
                  |____________________|   |____________________|

五、模式優劣分析

優勢:

  • 動態擴展功能,比繼承更靈活
  • 符合開閉原則,無需修改現有代碼
  • 支持多層嵌套裝飾
  • 不同裝飾類可自由組合

劣勢:

  • 多層裝飾增加代碼複雜度
  • 裝飾順序影響最終結果
  • 可能產生大量小類
  • 調試困難(需逐層檢查裝飾)

六、應用場景

  1. 動態擴展對象功能
    (如為圖形界面組件添加邊框、滾動條)
  2. 撤銷功能實現
    (通過裝飾記錄操作歷史)
  3. 數據流處理
    (Java I/O中的緩衝、加密處理)
  4. 權限控制
    (通過裝飾添加權限校驗層)
  5. 日誌記錄
    (為業務邏輯添加日誌裝飾)

七、Java標準庫應用

Java I/O流典型實現:

// 多層裝飾示例
InputStream in = new FileInputStream("data.txt");
in = new BufferedInputStream(in);      // 添加緩衝功能
in = new GZIPInputStream(in);          // 添加解壓縮功能
in = new Base64InputStream(in);        // 添加Base64解碼

// 自定義裝飾者示例
class UppercaseInputStream extends FilterInputStream {
    public UppercaseInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        int c = super.read();
        return (c == -1) ? c : Character.toUpperCase(c);
    }
}

八、高級應用技巧

透明性控制
通過接口繼承保持裝飾透明性:

interface Window {
    void draw();
}

class BasicWindow implements Window { /*...*/ }

abstract class WindowDecorator implements Window {
    protected Window window;
    // 不暴露額外方法
}

裝飾順序控制
使用建造者模式管理裝飾順序:

public class CoffeeBuilder {
    private Coffee coffee = new SimpleCoffee();
    
    public CoffeeBuilder addMilk() {
        coffee = new MilkDecorator(coffee);
        return this;
    }
    
    public Coffee build() {
        return coffee;
    }
}

動態移除裝飾
實現裝飾棧管理:

public class UndoableCoffee implements Coffee {
    private Deque<Coffee> stack = new ArrayDeque<>();
    
    public UndoableCoffee(Coffee coffee) {
        stack.push(coffee);
    }
    
    public void addDecorator(CoffeeDecorator decorator) {
        stack.push(decorator);
    }
    
    public void undo() {
        if (stack.size() > 1) {
            stack.pop();
        }
    }
    
    // 實現Coffee接口方法...
}

九、最佳實踐建議

  1. 保持組件接口簡潔
    避免裝飾者需要實現過多無關方法
  2. 控制裝飾層次深度
    建議不超過4層裝飾
  3. 優先使用透明裝飾
    保持裝飾前後接口一致
  4. 注意線程安全問題
    對於可變狀態裝飾器,使用同步控制
  5. 性能敏感場景慎用
    多層裝飾可能影響性能(建議結合對象池)
user avatar debuginn 頭像 seazhan 頭像 xuxueli 頭像 AmbitionGarden 頭像 tech 頭像 lvlaotou 頭像 ahahan 頭像 lenve 頭像 lu_lu 頭像 boxuegu 頭像 chaochenyinshi 頭像 tuhooo 頭像
點贊 51 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.