來一局緊張刺激的吃雞——淺談裝飾者模式

来源:https://www.cnblogs.com/MrJR/archive/2019/03/01/10454342.html
-Advertisement-
Play Games

裝飾者模式 想看本系列前作的朋友可以點擊下麵鏈接哦。 一起去開心的購物吧——淺談觀察者模式 記一場精彩的籃球比賽——淺談策略模式 大家好,又跟大家見面啦,今天呢,我與大家分享一個新的Java設計模式——裝飾者模式。 首先,不能免俗的我們來看一下官方給的定義: 裝飾者模式動態地將責任附加到對象上。若要 ...


裝飾者模式

聲明:本文為原創,如有轉載請註明轉載與原作者並提供原文鏈接,僅為學習交流,本人才識短淺,如有錯誤,敬請指正

想看本系列前作的朋友可以點擊下麵鏈接哦。

一起去開心的購物吧——淺談觀察者模式

記一場精彩的籃球比賽——淺談策略模式

 

大家好,又跟大家見面啦,今天呢,我與大家分享一個新的Java設計模式——裝飾者模式。

首先,不能免俗的我們來看一下官方給的定義:

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

通過這個官方定義,我們也許還理不清這是一個怎麼樣的設計模式,但是大家肯定都會覺得這絕對是一個非常靈活的適合後期維護的設計模式,為什麼呢,短短的一句話中,我們發現了動態,擴展功能,更有彈性這些令人激動的詞語(至少對維護一群“屎山”代碼的程式員來說足夠讓人激動),同時,這個設計模式還直接diss了Java中一個非常普遍的概念,繼承,這時候也許就會有支持“繼承”的擁躉出來吶喊:憑什麼這麼說我家愛豆,她發高燒50度還在堅持構建對象,實在是太偉大了。OKOK,稍後我們會說明原因滴,此處我們先表下不提。

最近有一款游戲呢非常的火爆,他就是風暴英。。咳咳(風暴要火),他就是APEX,作為一款吃雞類型的游戲,她承接了從H1Z1到絕地求生到各種吃雞手游的熱度,可以說目前是非常的火爆,對於這種類型的游戲,相信各位看官不會感到陌生,不少人估計更是忠實玩家,在這種開局一個人,裝備全靠撿的游戲中,擁有一把好槍無疑是勝利的最佳保障(伏地魔除外,苟就完事了),而一把好槍,除了槍本身之外,還有眾多的組件可供搭配,從消音器到瞄準鏡再到握把,將不同的組件組裝到一把槍中,最終就可以擁有一把威力強大的好槍。

裝飾者模式便是實現了這樣的功能。

在裝飾者模式中,有著兩個最重要的角色,一個稱為裝飾者,另一個稱為被裝飾者,被裝飾者通過裝飾者“裝飾”自己,而裝飾者可以在被裝飾者的行為之前或之後加上自己的行為,已達到特定的行為目的。

那麼現在是時候開始我們的吃雞之旅了。在游戲中,被裝飾者就是“槍”。我們首先定義一個被裝飾者介面,用於定義被裝飾者的行為。

public interface Gun {

    String getName();

    String showPower();
}

第一個方法用於返回槍的名稱,隨著組件的增加,槍的名稱會發生變化。第二個方法用於展示當前槍的威力,當然我們是用一句話來形容而不是真的開一槍。

接下來我們定義一個裝飾者介面,即各種組件的介面

public interface Unit extends Gun{

    @Override
    String getName();
}

此處,我們發現,組件介面繼承了槍介面,並且會重寫Gun中的getName方法,這裡我們可以得出結論,在裝飾者模式中,裝飾者和被裝飾者對象有相同的超類型!

然後我們該定義幾個具體被裝飾者了,在這裡,我們會定義M16與98K兩種型號的槍充當具體被裝飾者

public class _98K implements Gun {

    private String power = "一把威力巨大的98K";
    private String name = "98K";

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String showPower() {
        return power;
    }
}
public class M16 implements Gun {

    private String power = "一把射速很快的M16";
    private String name = "M16";

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String showPower() {
        return power;
    }
}

兩個具體被裝飾者大同小異,不再贅述。

然後是我們的幾個具體組件對象,此處呢,我們定義了三種組件以供搭配——八倍鏡,擴容彈夾,握把。

public class Grip implements Unit {

    private Gun gun;

    private String function = ",加裝握把,提高射擊穩定性";
    private String name = "握把";

    public Grip(Gun gun){
        this.gun = gun;
    }

    @Override
    public String getName() {
        return gun.getName() + "+" + name;
    }

    @Override
    public String showPower() {
        return gun.showPower() + function;
    }
}

我們仔細來看這個握把的具體實現類,我們發現,它維護了一個被裝飾者的引用,併在構造方法中將其初始化,隨後實現介面定義的方法,在調用被裝飾者的方法時,我們還夾帶了一點私貨,還記得上面的話嗎:裝飾者可以在被裝飾者的行為之前或之後加上自己的行為,已達到特定的行為目的!在這裡,我們真正實現了“裝飾”這一步。

同樣得,還有八倍鏡組件以及擴容彈夾組件

public class SightTelescope implements Unit {

    private Gun gun;
    private String name = "八倍鏡";
    private String function = ",加上八倍鏡,射擊更加精準";

    public SightTelescope(Gun gun){
        this.gun = gun;
    }

    @Override
    public String getName() {
        return gun.getName() + "+" + name;
    }

    @Override
    public String showPower() {
        return gun.showPower() + function;
    }
}
public class ExpansionCartridgeClip implements Unit {

    private Gun gun;
    private String name = "擴容彈夾";
    private String function = ",換裝擴容彈夾,絕對火力壓制";

    public ExpansionCartridgeClip(Gun gun){
        this.gun = gun;
    }

    @Override
    public String getName() {
        return gun.getName() + "+" + name;
    }

    @Override
    public String showPower() {
        return gun.showPower() + function;
    }
}

至此,我們已經成功定義了我們所有的裝飾者與被裝飾者,趕快開始這一局緊張刺激的吃雞吧。我們的裝飾者模式將在游戲中經受考驗。

public class Game {

    public static void main(String[] args) {

        Gun _98k = new _98K();
        show(_98k);
        _98k = new ExpansionCartridgeClip(_98k);
        show(_98k);
        _98k = new SightTelescope(_98k);
        show(_98k);

        Gun m16 = new M16();
        show(m16);
        m16 = new Grip(m16);
        show(m16);
        m16 = new ExpansionCartridgeClip(m16);
        show(m16);
        m16 = new SightTelescope(m16);
        show(m16);

    }

    private static void show(Gun gun){
        System.out.println("擁有了" + gun.getName() + "\n" + gun.showPower());
    }
}

我們首先創建了98k的對象,使用列印方法查看它的狀態,然後我們的裝飾者,也就是組件開始對98k進行裝飾,我們正在組裝一把威力強大的98K,有人也許想問,為啥new出來的組件對象可以直接賦值給98k對象呢,別忘了,裝飾者模式的關鍵,裝飾者和被裝飾對象有著相同的超類型。

同樣的,我們使用組件裝飾了一把m16步槍,是時候開火了,讓我們看看到底這些槍有沒有按照我們的想法正常工作呢?

 

 duang,就像加了許多特技,我們的槍再也不用裸奔了,他現在是擁有很多組件的大殺器,是時候送快遞大吉大利,今晚吃雞了。

如果我們喜歡,還可以再加上很多的組件,只要它實現了裝飾者介面並按照正確的方式實現,我們就可以在運行時動態的,不限量地使用它來裝飾對象,而且不用修改原有的代碼,對象可以在任何時候被裝飾,只要它的確是一個被裝飾者(實現了被裝飾者的介面),而這些,都是單純的繼承無法實現的,這也就是為什麼我們開頭所說,裝飾者提供了比繼承更具有彈性的方案。這個模式再次著重表現了我們的一個設計原則——對修改關閉,對擴展開放!

感謝大家聽我絮絮叨叨這麼久,那麼裝飾者模式的淺談就先進行到這裡,不說了,我先吃雞去了(^O^)


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

-Advertisement-
Play Games
更多相關文章
  • 一、業務開發與基礎開發的區別 - 劃分方式 一種將後臺開發細分的方式:前臺開發(業務)、中台開發(中間件、應用基礎服務、PAAS服務、IAAS服務)、後臺開發(運維開發)。一般前臺開發對應於業務開發,中台開發對應基礎開發,後臺開發對應運維。 - 規模 基礎開發的目標是解決業務的公共痛點,所以一般數據 ...
  • 分散式系統是由一組通過網路進行通信、為了完成共同的任務而協調工作的電腦節點組成的系統。分散式系統的出現是為了用廉價的、普通的機器完成單個電腦無法完成的計算、存儲任務。其目的是利用更多的機器,處理更多的數據。 一、第一階段 最初假設的網站中,我們把應用系統網站、文件和資料庫都放在一臺伺服器上,一臺 ...
  • 前言:通過設計器交互來創建流程圖是比較常見的方式,這種方式是比較方便業務人員對流程的操作。然而,在需要流程模板,或者技術開發階段以及一些自動化流程的處理過程中,使用代碼快速創建流程圖也是一種非常有必要的快捷途徑。本文重點說明這種方法的實現過程和具體使用價值。 1. 互動式構建流程圖 圖形互動式一般是 ...
  • LieBrother原文 : "行為型模式:迭代器模式" 十一大行為型模式之六:迭代器模式。 簡介 姓名 :迭代器模式 英文名 :Iterator Pattern 價值觀 :人生沒有回頭路 個人介紹 : Provide a way to access the elements of an aggre ...
  • 定義:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象 原型模式其實就是通過一個對象來創建一個新的可定製(可以是源對象的一個副本也可以有所改變)的對象,而且我們並不需要知道具體創建的細節。在java中使用原型模式是非常簡單的,因為Object類中提供了一個本地方法clone,就是用來拷 ...
  • PHP語言在Linux系統上運行的時候,需要在Linux系統上部署相應的Nginx、MySQL、PHP等環境,只有將這些環境參數都設置好,PHP相關應用程式才可正常運行,部署環境的方法有很多種,可手動模式下一個個軟體環境進行安裝,也可使用工具進行快速部署,此文以阿裡雲的Centos系統為例,介紹在C ...
  • 這一篇博客,還是接著說那些常見的反爬蟲措施以及我們的解決辦法。同樣的,如果對你有幫助的話,麻煩點一下推薦啦。 一、防盜鏈 這次我遇到的防盜鏈,除了前面說的Referer防盜鏈,還有Cookie防盜鏈和時間戳防盜鏈。Cookie防盜鏈常見於論壇、社區。當訪客請求一個資源的時候,他會檢查這個訪客的Coo ...
  • FPM(FastCGI Process Manager)是PHP FastCGI運行模式的一個進程管理器,從它的定義可以看出,FPM的核心功能是進程管理,那麼它用來管理什麼進程呢?這個問題就需要從FastCGI說起了。 FastCGI是Web伺服器(如:Nginx、Apache)和處理程式之間的一種 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...