設計模式——裝飾者模式

来源:http://www.cnblogs.com/zuiaixiaoniao/archive/2016/10/24/5992890.html
-Advertisement-
Play Games

轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/24269409 裝飾者模式:若要擴展功能,裝飾者提供了比集成更有彈性的替代方案,動態地將責任附加到對象上。 先簡單描述下裝飾者模式發揮作用的地方,當我們設計好了一個類,我們需要給這個 ...


轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/24269409

裝飾者模式:若要擴展功能,裝飾者提供了比集成更有彈性的替代方案,動態地將責任附加到對象上。

先簡單描述下裝飾者模式發揮作用的地方,當我們設計好了一個類,我們需要給這個類添加一些輔助的功能,並且不希望改變這個類的代碼,這時候就是裝飾者模式大展雄威的時候了。這裡還體現了一個原則:類應該對擴展開放,對修改關閉。

下麵進入正題,今天在那看電影,忽然想起年輕時在游戲場上的血雨腥風啊,哈哈,下麵以游戲為背景介紹裝飾者模式。玩過游戲的兄弟應該都知道,游戲裡面每個角色有武器、鞋子、護腕、戒指、還有各種紅寶石、藍寶石、黃寶石等等。

下麵需求開始:設計游戲的裝備系統,基本要求,要可以計算出每種裝備在鑲嵌了各種寶石後的攻擊力和描述:

具體需求:

1、武器(攻擊力20) 、戒指(攻擊力5)、護腕(攻擊力5)、鞋子(攻擊力5)

2、藍寶石(攻擊力5/顆)、黃寶石(攻擊力10/顆)、紅寶石(攻擊力15/顆)

3、每個裝備可以隨意鑲嵌3顆

 好了,需求介紹完畢,當然了,不要吐槽我的設計,尼瑪鞋子哪來的攻擊力,關鍵時刻也是可以砸人的嘛。下麵開始初步的設想,出於多年面向對象的經驗,我們可能會這麼設計:

如果你這麼設計了,我靠,就這麼點需求你寫了幾百個類,隨便添加兩個寶石,哈哈,指數增長聽過麽,準備加班吧。

可能你還會這麼設計:寫一個超類,然後裡面各種set寶石,然後在計算攻擊力的地方,使勁的If有哪幾種寶石,恭喜你,代碼量不是很大,但是隨便添加個武器,你得又多寫多少個IF呢。

上面敘述了一些可能性的設計,都不是很好,下麵看看如何將裝飾者模式融入:

首先是裝備的超類

package com.zhy.pattern.decorator;

/**
 * 裝備的介面
 * 
 * @author zhy
 * 
 */
public interface IEquip
{

    /**
     * 計算攻擊力
     * 
     * @return
     */
    public int caculateAttack();

    /**
     * 裝備的描述
     * 
     * @return
     */
    public String description();
}

 

然後分別是武器、戒指、護腕、鞋子

package com.zhy.pattern.decorator;

/**
 * 武器
 * 攻擊力20
 * @author zhy
 * 
 */
public class ArmEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 20;
    }

    @Override
    public String description()
    {
        return "屠龍刀";
    }

}
 

package com.zhy.pattern.decorator;

/**
 * 戒指
 * 攻擊力 5
 * @author zhy
 *
 */
public class RingEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 5;
    }

    @Override
    public String description()
    {
        return "聖戰戒指";
    }

}
 

package com.zhy.pattern.decorator;

/**
 * 護腕
 * 攻擊力 5
 * @author zhy
 *
 */
public class WristEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 5;
    }

    @Override
    public String description()
    {
        return "聖戰護腕";
    }

}
 

package com.zhy.pattern.decorator;

/**
 * 鞋子
 * 攻擊力 5
 * @author zhy
 * 
 */
public class ShoeEquip implements IEquip
{

    @Override
    public int caculateAttack()
    {
        return 5;
    }

    @Override
    public String description()
    {
        return "聖戰靴子";
    }

}

 


接下來當然是裝飾品,寶石了,首先超類

package com.zhy.pattern.decorator;

/**
 * 裝飾品的介面
 * @author zhy
 *
 */
public interface IEquipDecorator extends IEquip
{
    
}

 

下來藍寶石、黃寶石、紅寶石

package com.zhy.pattern.decorator;

/**
 * 藍寶石裝飾品
 * 每顆攻擊力+5
 * @author zhy
 * 
 */
public class BlueGemDecorator implements IEquipDecorator
{
    /**
     * 每個裝飾品維護一個裝備
     */
    private IEquip equip;

    public BlueGemDecorator(IEquip equip)
    {
        this.equip = equip;
    }

    @Override
    public int caculateAttack()
    {
        return 5 + equip.caculateAttack();
    }

    @Override
    public String description()
    {
        return equip.description() + "+ 藍寶石";
    }

}
 

package com.zhy.pattern.decorator;

/**
 * 黃寶石裝飾品
 * 每顆攻擊力+10
 * @author zhy
 * 
 */
public class YellowGemDecorator implements IEquipDecorator
{
    /**
     * 每個裝飾品維護一個裝備
     */
    private IEquip equip;

    public YellowGemDecorator(IEquip equip)
    {
        this.equip = equip;
    }

    @Override
    public int caculateAttack()
    {
        return 10 + equip.caculateAttack();
    }

    @Override
    public String description()
    {
        return equip.description() + "+ 黃寶石";
    }

}
 

package com.zhy.pattern.decorator;

/**
 * 紅寶石裝飾品 每顆攻擊力+15
 * 
 * @author zhy
 * 
 */
public class RedGemDecorator implements IEquipDecorator
{
    /**
     * 每個裝飾品維護一個裝備
     */
    private IEquip equip;

    public RedGemDecorator(IEquip equip)
    {
        this.equip = equip;
    }

    @Override
    public int caculateAttack()
    {
        return 15 + equip.caculateAttack();
    }

    @Override
    public String description()
    {
        return equip.description() + "+ 紅寶石";
    }

}

 

好了,到此結束,我們已經實現了需求的功能了,是不是每個類都很清晰加簡單,下麵看測試:

package com.zhy.pattern.decorator;

public class Test
{
    public static void main(String[] args)
    {
        // 一個鑲嵌2顆紅寶石,1顆藍寶石的靴子
        System.out.println(" 一個鑲嵌2顆紅寶石,1顆藍寶石的靴子");
        IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));
        System.out.println("攻擊力  : " + equip.caculateAttack());
        System.out.println("描述 :" + equip.description());
        System.out.println("-------");
        // 一個鑲嵌1顆紅寶石,1顆藍寶石的武器
        System.out.println(" 一個鑲嵌1顆紅寶石,1顆藍寶石,1顆黃寶石的武器");
        equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));
        System.out.println("攻擊力  : " + equip.caculateAttack());
        System.out.println("描述 :" + equip.description());
        System.out.println("-------");
    }
}

 

輸出:

    一個鑲嵌2顆紅寶石,1顆藍寶石的靴子
    攻擊力  : 40
    描述 :聖戰靴子+ 藍寶石+ 紅寶石+ 紅寶石
    -------
    一個鑲嵌1顆紅寶石,1顆藍寶石,1顆黃寶石的武器 
    攻擊力 : 50 
    描述 :屠龍刀+ 黃寶石+ 藍寶石+ 紅寶石
    -------

 

 


贊不贊,要是需求隨便多幾個裝備,幾種寶石,我們隨隨便便就可以加上,然後開開心心下班。

好了,恭喜你,你又學會了一個設計模式,裝飾者模式。

現在根據例子對定義的理解,不用我多說吧。

 

Java的API中也有裝飾者模式的身影,如果你初學Java,一定記得Java裡面的各種流,很痛苦吧,但是當你明

白你們的設計之後就會感覺清晰很多。

把InputStream看作我們的IEquip,把FilterInputStream看作我們的IEquipDecorator,是不是和我們的設計幾乎一樣~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、java提供了三種ClassLoader對Class進行載入: 1.BootStrap ClassLoader:稱為啟動類載入器,是Java類載入層次中最頂層的類載入器,負責載入JDK中的核心類庫,如:rt.jar、resources.jar、charsets.jar等,可通過如下程式獲得該類加 ...
  • 20161021問題解析請點擊今日問題下方的“【Java每日一題】20161024”查看 今日問題: 請問主程式輸出結果是?(點擊以下“【Java每日一題】20161024”查看20161021問題解析) 題目原發佈於公眾號、簡書:【Java每日一題】20161024,【Java每日一題】20161 ...
  • 當比較簡單類型時(如String int float bool),判斷的是"相等 && 類型一樣" 比較對象時,判斷的是"是否指向同一個對象" ...
  • 深度優先搜索 # Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: ...
  • OJ搭建好了後,我們要熟悉一下OJ項目下的文件及文件夾。 首先,安裝好的OJ是在目錄var/www/html下。 html下的php文件 這些php文件都是些主要跳轉頁面。 admin文件夾 登錄管理員賬號後管理的管理界面 bootstrap文件夾 css樣式和圖片,如果要修改某些頁面的小地方請到w ...
  • 本節介紹TreeSet,相比HashSet,它有什麼不同?除了Set介面,它實現的SortedSet和NavigatableSet介面有哪些方法?它內部是如何實現的?... ...
  • ...
  • day03員工的添加,修改,刪除 修改功能 思路 : 點擊修改員工數據之後,跳轉到單行文本,查詢要修改的員工id的全部信息,主鍵id設置為readonly,其餘的都可以修改, 修改之後,提交按鈕,提交之後跳轉到全部員工界面 修改界面 : 部分代碼 : 刪除員工信息 那就相對簡單了,點擊刪除之後,帶上 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...