Design Pattern:Decorator Pattern 說明

主要概念為 Client 只需要 reference Thing object,可以有多種實作方式,並且定義 Decorator 包裝每一個SpecificThiing 的內容。同時,也可以衍生 SpecifiecDecorator 定義特定要包裝的介面,其他的介面就直接透過 Decorator delegate to SpecificThiing,或者做統一的包裝。

 

透過 Decorator 將每一個特定條件記錄在特定的 class 內,減少 if 判斷,增加理解能力。

舉例如下:

我們有一個 Hat class 定義:

public interface Hat {
    public String getName();
    public int getPrice();
    public String getDescription();
    public boolean isPremium();
}

主要商品為 StandardHat & PreminumHat

public class StandardHat implements Hat {
    private String name;
    public StandardHat(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public int getPrice() {
        return 2000;
    }
    public String getDescription() {
        return getName();
    }
    public boolean isPremium() {
        return false;
    }
}
public class PremiumHat implements Hat {
    private String name;
    public PremiumHat(String name) {
        this.name = name;
    }
 
    public String getName() {
        return name;
    }
 
    public int getPrice() {
        return 3000;
    }
   
    public String getDescription() {
        return getName();
    }
   
    public boolean isPremium() {
        return true;
    }
}

定義 DecoratorHat 處理所有 Decorator 共通的項目(例如回傳名稱):

public abstract class DecoratedHat implements Hat {
 
    private Hat decoratedHat;
 
    protected DecoratedHat(Hat decoratedHat) {
        this.decoratedHat = decoratedHat;
    }
 
    public String getName() {
        return decoratedHat.getName();
    }
 
    protected Hat getDecoratedHat() {
        return decoratedHat;
    }
}

透過 RibbonHat 可以在 Hat 上加裝緞帶:

public class RibbonedHat extends DecoratedHat {
      
    public RibbonedHat(Hat decoratedHat) {
        super(decoratedHat);
    }
   
    public int getPrice() {
        return getDecoratedHat().getPrice() + 100;
    }
   
    public String getDescription() {
        return getDecoratedHat().getDescription() + ", ribboned";
    }
   
    public boolean isPremium() {
        return getDecoratedHat().isPremium();
    }
}

GoldDecorator 塗上金色:

public class GoldenHat extends DecoratedHat {
      
    public GoldenHat(Hat decoratedHat) {
        super(decoratedHat);
    }
   
    public int getPrice() {
        if (isPremium()) {
            return getDecoratedHat().getPrice() + 1000;
        } else {
            return getDecoratedHat().getPrice() + 200;
        }
    }
   
    public String getDescription() {
        return "golden " + getDecoratedHat().getDescription();
    }
   
    public boolean isPremium() {
        return getDecoratedHat().isPremium();
    }
}

Decorator 的使用方式如下:

public void testGoldenRibbonedStandardHat() {
    Hat hat = new RibbonedHat(new GoldenHat(new StandardHat("baseball cap")));
        
    assertThat(hat.getPrice(), is(2300));
    assertThat(hat.getDescription(), is("golden baseball cap, ribboned"));
}

 

有問題嗎?歡迎一起討論喔!