Coding-21-裝飾器模式

  實現一個同樣功能可以有各種方法,功能簡單時需要考慮的只有效率和可讀性,功能複雜時就需要額外考慮擴展性。在設計程序時,使用合適的設計模式,不僅可以解決擴展性問題,還可以讓程序結構更符合人類的思維直覺,富有藝術感。
  這裏介紹了裝飾器模式

  裝飾器模式的說明是:動態地將責任(或功能)附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。

  Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.

Talk is cheap, show me code

  以 HTML 的渲染爲例,對一段文本 “hello world” 進行渲染,例如加黑、加斜體。

  • Python 的裝飾器
# 加黑裝飾器
def renderbold(func):
    def wrapped():
        return "<b>" + func() + "</b>"
    return wrapped

# 加斜體裝飾器
def renderitalic(func):
    def wrapped():
        return "<i>" + func() + "</i>"
    return wrapped

# 自下而上調用裝飾器
@renderbold
@renderitalic
def helloworld():
    return "hello world"

print(helloworld()) 
## 返回 <b><i>hello world</i></b>
  • Java 實現裝飾器
/* 基礎抽象類 */
abstract class HtmlRender{
    // 抽象地方法
    public abstract String render();
}
/* 實體類,提供文本 */
class HelloWorldHtml extends HtmlRender{
    @Override
    public String render(){
        return "hello world";
    }
}
/* 裝飾器抽象類,和實體類一樣,繼承了基礎抽象類:裝飾之後的對象的基礎類型不變,只是多了一些責任 */
abstract class HtmlDecorator extends HtmlRender{
    private HtmlRender htmlrender = null;
    public HtmlDecorator(HtmlRender htmlrender){
        this.htmlrender = htmlrender;
    }
    @Override
    public String render(){
        return this.htmlrender.render();
    }
}
/* 裝飾器實體類,加黑裝飾器 */
class BoldDecorator extends HtmlDecorator{
    public BoldDecorator(HtmlRender htmlrender){
        super(htmlrender);
    }
    // 重寫父類的方法
    public String render(){
        String str = super.render();
        return("<b>" + str + "</b>");
    }
}
/* 裝飾器實體類,加斜體飾器 */
class ItalicDecorator extends HtmlDecorator{
    public ItalicDecorator(HtmlRender htmlrender){
        super(htmlrender);
    }
    // 重寫父類的方法
    public String render(){
        String str = super.render();
        return("<i>" + str + "</i>");
    }
}
class DecoratorDemo{
    public static void main(String[] args){
        HtmlRender htmlrender = new HelloWorldHtml();
        // 第一次修飾,加斜體
        htmlrender = new ItalicDecorator(htmlrender);
        // 第二次修飾,加黑
        htmlrender = new BoldDecorator(htmlrender);
        // 渲染完畢
        System.out.println(htmlrender.render());
    }
}

// 輸出結果 <b><i>hello world</i></b>
總結
  • Python 的裝飾器是語法的一部分,由於函數也是對象,可以直接裝飾函數,使用更直觀(像一個真實的裝飾品),但是定義裝飾器函數語法不太直觀,使用了閉包函數;
  • Java 的裝飾器是一種面向對象的設計模式,使用了普通語法實現稍微複雜,且使用起來並且不太直觀;
  • 一些簡單基本的功能不建議使用裝飾器,會影響可讀性。
參考資料

https://www.cnblogs.com/volcano-liu/p/10897897.html
https://www.jianshu.com/p/ab702e4d4ba7

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章