設計模式 - 裝飾者模式 (Structural Patterns - Decorator Design Pattern)

前言

Wiki對於 Decorator Pattern的定義如下:

The Decorator [3] design pattern is one of the twenty-three well-known GoF design patterns that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.

Decorator模式最主要有兩點

  • 圍繞著一個核心,創建hierarchy(階層體系)
  • 讓核心被包裝在它的子物件中,增加功能

類別圖

  • 根據要增加功能的核心,創建Decorator
  • 讓核心可以被Decorator hierarchy的物件包裝

範例

英雄升階層範例,現在老闆要開放一個新功能,讓英雄可以根據等級升階。

英雄 -> 戰士 -> 騎士 / 聖騎士

而我們就以上面的升階當作Decorator的範例

說明:

  • 英雄介面宣告攻擊行為
  • 創建基本戰士Class
  • 創建進階戰士Decorator
  • 騎士和十字軍繼承Decorator並且延伸攻擊方法
interface Hero {
    void attack();
}

class Warrior implements Hero {

    @Override
    public void attack() {
        System.out.println("Warrior attck");
    }
}


abstract class IntermediateWarriorDecorator implements Hero{
    private Hero warrior;

    public IntermediateWarriorDecorator(Hero warrior) {
        this.warrior = warrior;
    }

    public void originalAttack() {
        warrior.attack();
    }
}

class Knight extends IntermediateWarriorDecorator {

    public Knight(Hero warrior) {
        super(warrior);
    }

    @Override
    public void attack() {
        super.originalAttack();
        System.out.println("Knight attack");
    }
}

class Crusader extends IntermediateWarriorDecorator {

    public Crusader(Hero warrior) {
        super(warrior);
    }

    @Override
    public void attack() {
        super.originalAttack();
        System.out.println("Crusader attack");
    }
}



public class Decorator {
    public static void main(String[] args) {
        Hero knight = new Knight(new Warrior());
        Hero crusader = new Crusader(new Warrior());

        knight.attack();
        crusader.attack();
    }
}

結論

Decorator最常用來研展Class物件的功能,最常見也是最常用的案例就是I/O stream

FileInputStream fis = new FileInputStream("/objects.gz");
BufferedInputStream bis = new BufferedInputStream(fis);
GzipInputStream gis = new GzipInputStream(bis);
ObjectInputStream ois = new ObjectInputStream(gis);
SomeObject someObject = (SomeObject) ois.readObject();

而Decorator使用時機

  • 當你需要研展一個物件功能時 (透過Decorator將你新增的功能加在子類別)

留言

這個網誌中的熱門文章

Java Lambda Map篇

(InterviewBit) System Design - Design Cache System

設計模式 - 享元模式 (Structural Patterns - Flyweight Design Pattern)