最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java經(jīng)典設(shè)計(jì)模式之裝飾器模式解析

 更新時(shí)間:2023年08月16日 11:50:38   作者:也曾眼眸有光  
這篇文章主要介紹了Java經(jīng)典設(shè)計(jì)模式之裝飾器模式解析,裝飾器模式主要解決繼承關(guān)系過(guò)于復(fù)雜的問(wèn)題,通過(guò)組合來(lái)替代繼承,指在不改變現(xiàn)有對(duì)象結(jié)構(gòu)的情況下,動(dòng)態(tài)地給該對(duì)象增加一些職責(zé)(即增加其額外功能)的模式,需要的朋友可以參考下

裝飾器模式

裝飾器模式主要解決繼承關(guān)系過(guò)于復(fù)雜的問(wèn)題,通過(guò)組合來(lái)替代繼承。

指在不改變現(xiàn)有對(duì)象結(jié)構(gòu)的情況下,動(dòng)態(tài)地給該對(duì)象增加一些職責(zé)(即增加其額外功能)的模式,裝飾器模式提供了比繼承更有彈性的替代方案將功能附加到對(duì)象上。

因此,裝飾器模式的核心功能是功能擴(kuò)展,使用裝飾器模式可以透明且動(dòng)態(tài)的擴(kuò)展類(lèi)的功能。

裝飾器模式還有一個(gè)特點(diǎn),那就是可以對(duì)原始類(lèi)嵌套使用多個(gè)裝飾器。

為了滿(mǎn)足這個(gè)應(yīng)用場(chǎng)景,在設(shè)計(jì)的時(shí)候,裝飾器類(lèi)需要跟原始類(lèi)繼承相同的抽象類(lèi)或者接口。

應(yīng)用場(chǎng)景:

  1. 用于擴(kuò)展一個(gè)類(lèi)的功能,或者給一個(gè)類(lèi)添加附加職責(zé)
  2. 動(dòng)態(tài)的給一個(gè)對(duì)象添加功能,這些功能可以再動(dòng)態(tài)的被撤銷(xiāo)
  3. 需要為一批平行的兄弟類(lèi)進(jìn)行改裝或者加裝功能

UML類(lèi)圖

由上圖可知,裝飾器模式主要包含了4個(gè)角色;

  1. 抽象組建(Component):可以是一個(gè)接口或者抽象類(lèi),充當(dāng)被裝飾類(lèi)的原始對(duì)象,規(guī)定了被裝飾對(duì)象的行為
  2. 具體組件(ConcreteComponent):實(shí)現(xiàn)/繼承Component的一個(gè)具體對(duì)象,即被裝飾對(duì)象
  3. 抽象裝飾器(Decorator):通用的裝飾ConcreteComponent的裝飾器,其內(nèi)部必然有一個(gè)屬性指向Component,其實(shí)現(xiàn)一般是一個(gè)抽象類(lèi),主要為了讓其子類(lèi)按照其構(gòu)造形式傳入一個(gè)Component,這是強(qiáng)制的通用行為。如果系統(tǒng)中裝飾邏輯單一,則并不需要實(shí)現(xiàn)許多裝飾器,可以直接省略該類(lèi),而直接實(shí)現(xiàn)一個(gè)具體裝飾器即可
  4. 具體裝飾器(ConcreteDecorator):Decorator的具體實(shí)現(xiàn)類(lèi),理論上,每個(gè)ConcreteDecorator都擴(kuò)展了Component對(duì)象的一種功能

裝飾器模式的實(shí)現(xiàn)原理就是,讓裝飾器實(shí)現(xiàn)與被裝飾類(lèi)相同的接口,使得裝飾器與被擴(kuò)展類(lèi)類(lèi)型一致,并在構(gòu)造函數(shù)中傳入該接口對(duì)象,然后再實(shí)現(xiàn)這個(gè)接口的被 包裝類(lèi) 屬于同一類(lèi)型,且構(gòu)造函數(shù)的參數(shù)為其實(shí)現(xiàn)接口類(lèi),因此裝飾器模式具備嵌套擴(kuò)展功能,這樣就能使用裝飾器模式一層一層的對(duì)底層被包裝類(lèi)進(jìn)行功能擴(kuò)展了

通用寫(xiě)法

public class Client {
    public static void main(String[] args) {
        ConcreteComponent c1 = new ConcreteComponent();
        ConcreteDecoratorA decoratorA = new ConcreteDecoratorA(c1);
        decoratorA.operation();
        System.out.println("---------------------------");
        ConcreteDecoratorB decoratorB = new ConcreteDecoratorB(c1);
        decoratorB.operation();
        System.out.println("---------------------------");
        ConcreteDecoratorB decoratorB1 = new ConcreteDecoratorB(decoratorA);
        decoratorB1.operation();
    }
    static abstract class Component{
        public abstract void operation();
    }
    static class ConcreteComponent extends Component{
        @Override
        public void operation() {
            System.out.println("處理業(yè)務(wù)邏輯??!");
        }
    }
    static abstract class Decorator extends Component{
        protected Component component;
        public Decorator(Component component){
            this.component = component;
        }
        public void operation(){
            //轉(zhuǎn)發(fā)請(qǐng)求給組建對(duì)象,可以在轉(zhuǎn)發(fā)前后執(zhí)行一些附加動(dòng)作
            component.operation();
        }
    }
    static class ConcreteDecoratorA extends Decorator{
        public ConcreteDecoratorA(Component component) {
            super(component);
        }
        private void  operationFirst(){
            System.out.println("ConcreteDecoratorA裝飾operationFirst");
        }
        private void  operationLast(){
            System.out.println("ConcreteDecoratorA裝飾operationLast");
        }
        public void operation(){
            operationFirst();
            super.operation();
            operationLast();
        }
    }
    static class ConcreteDecoratorB extends Decorator{
        public ConcreteDecoratorB(Component component) {
            super(component);
        }
        private void  operationFirst(){
            System.out.println("ConcreteDecoratorB裝飾operationFirst");
        }
        private void  operationLast(){
            System.out.println("ConcreteDecoratorB裝飾operationLast");
        }
        public void operation(){
            operationFirst();
            super.operation();
            operationLast();
        }
    }
}

示例:使用裝飾器模式解決煎餅加碼問(wèn)題

下面用代碼來(lái)模擬給煎餅加碼的業(yè)務(wù)場(chǎng)景,先來(lái)看不用裝飾器模式的情況。

首先創(chuàng)建一個(gè)煎餅Battercake類(lèi)

public class Battercake {
    protected String getMsg(){
        return "煎餅";
    }
    public int getPrice(){
        return 5;
    }
}

然后創(chuàng)建一個(gè)加雞蛋的煎餅BattercakeWithEgg類(lèi)

public class BattercakeWithEgg extends Battercake{
    protected String getMsg(){
        return super.getMsg() + "+ 1個(gè)雞蛋";
    }
    public int getPrice(){
        return super.getPrice() + 1;
    }
}

在創(chuàng)建一個(gè)既加雞蛋又加香腸的BattercakeWithEggAndSausage類(lèi)

public class BattercakeWithEggAndSausage extends BattercakeWithEgg{
    protected String getMsg(){
        return super.getMsg() + "+ 1根香腸";
    }
    public int getPrice(){
        return super.getPrice() + 2;
    }
}

最后編寫(xiě)客戶(hù)端測(cè)試代碼

public class ClientTest {
    public static void main(String[] args) {
        Battercake battercake = new Battercake();
        System.out.println(battercake.getMsg() + ",總價(jià)格" + battercake.getPrice());
        BattercakeWithEgg battercakeWithEgg = new BattercakeWithEgg();
        System.out.println(battercakeWithEgg.getMsg() + ",總價(jià)格" + battercakeWithEgg.getPrice());
        BattercakeWithEggAndSausage battercakeWithEggAndSausage = new BattercakeWithEggAndSausage();
        System.out.println(battercakeWithEggAndSausage.getMsg() + ",總價(jià)格" + battercakeWithEggAndSausage.getPrice());
    }
}

運(yùn)行結(jié)果如下:

煎餅,總價(jià)格5
煎餅+ 1個(gè)雞蛋,總價(jià)格6
煎餅+ 1個(gè)雞蛋+ 1根香腸,總價(jià)格8

運(yùn)行結(jié)果沒(méi)有問(wèn)題。

但是,如果用戶(hù)需要一個(gè)加2個(gè)雞蛋和1根香腸的煎餅,則用現(xiàn)在的類(lèi)結(jié)構(gòu)是創(chuàng)建不出來(lái)的,也無(wú)法自動(dòng)計(jì)算出價(jià)格,除非再創(chuàng)建一個(gè)類(lèi)做定制。

如果需求在變,那么一直加定制顯然是不科學(xué)的

下面用裝飾器模式來(lái)解決上面的問(wèn)題。首先創(chuàng)建一個(gè)煎餅的抽象Battercake類(lèi)。

public abstract class Battercake {
    protected abstract String getMsg();
    protected abstract int getPrice();
}

創(chuàng)建一個(gè)基本的煎餅(或者叫基礎(chǔ)套餐)BaseBattercake.

public class BaseBattercake extends Battercake{
    @Override
    protected String getMsg() {
        return "煎餅";
    }
    @Override
    protected int getPrice() {
        return 5;
    }
}

然后創(chuàng)建一個(gè)擴(kuò)張?zhí)撞偷某橄笱b飾器BattercakeDecotator類(lèi)

public abstract class BattercakeDecotator extends Battercake{
    private Battercake battercake;
    public BattercakeDecotator(Battercake battercake){
        this.battercake = battercake;
    }
    protected abstract void doSomething();
    protected String getMsg(){
        return this.battercake.getMsg();
    }
    protected int getPrice(){
        return this.battercake.getPrice();
    }
}

接著創(chuàng)建雞蛋裝飾器EggDecorator

public class EggDecorator extends BattercakeDecotator{
    public EggDecorator(Battercake battercake) {
        super(battercake);
    }
    @Override
    protected void doSomething() {
    }
    protected String getMsg(){
        return super.getMsg() + "+1個(gè)雞蛋";
    }
    protected int getPrice(){
        return super.getPrice() + 1;
    }
}

創(chuàng)建香腸裝飾器SausageDecorator類(lèi)

public class SausageDecorator extends BattercakeDecotator{
    public SausageDecorator(Battercake battercake) {
        super(battercake);
    }
    @Override
    protected void doSomething() {
    }
    protected String getMsg(){
        return super.getMsg() + "+1根香腸";
    }
    protected int getPrice(){
        return super.getPrice() + 2;
    }
}

在編寫(xiě)客戶(hù)端測(cè)試代碼

public class Client {
    public static void main(String[] args) {
        //買(mǎi)一個(gè)煎餅
        Battercake battercake;
        battercake = new BaseBattercake();
        //煎餅有點(diǎn)小,想再加1個(gè)雞蛋
        battercake = new EggDecorator(battercake);
        battercake = new EggDecorator(battercake);
        battercake = new SausageDecorator(battercake);
        System.out.println(battercake.getMsg() + ",總價(jià): " + battercake.getPrice());
    }
}

運(yùn)行結(jié)果如下圖所示:

煎餅+1個(gè)雞蛋+1個(gè)雞蛋+1根香腸,總價(jià): 9

裝飾器模式與代理模式區(qū)別

從代理模式的UML類(lèi)圖和通用代碼實(shí)現(xiàn)上看,代理模式與裝飾器模式幾乎一摸一樣。

代理模式的Subject對(duì)應(yīng)裝飾器模式的Component,代理模式的RealSubject對(duì)應(yīng)裝飾器模式的Concrete Component,代理模式的Proxy對(duì)應(yīng)的裝飾器模式的Decorator。

確實(shí),從代碼實(shí)現(xiàn)上看,代理模式的確與裝飾器模式是一樣的,但是這兩種設(shè)計(jì)模式多面向的功能擴(kuò)展面是不一樣的。

裝飾器模式強(qiáng)調(diào)自身功能的擴(kuò)展。

Decorator所做的就是增強(qiáng)ConcreteComponent的功能,主體對(duì)象為ConcreteComponent,著重類(lèi)功能的變化。

代理模式強(qiáng)調(diào)對(duì)代理過(guò)程的控制。

Proxy完全掌握對(duì)RealSubject的訪(fǎng)問(wèn)控制,因此,Proxy可以決定對(duì)RealSubject進(jìn)行功能擴(kuò)展,功能縮減甚至功能散失,主體對(duì)象為Proxy。

裝飾器模式優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 裝飾器是繼承的有力補(bǔ)充,比繼承靈活,在不改變?cè)袑?duì)象的情況下,動(dòng)態(tài)地給一個(gè)對(duì)象擴(kuò)展功能,即插即用。
  • 通過(guò)使用不同裝飾類(lèi)及這些裝飾類(lèi)的排列組合,可以實(shí)現(xiàn)不同效果
  • 裝飾器模式完全遵守開(kāi)閉原則

缺點(diǎn):

  • 會(huì)出現(xiàn)更多的代碼,更多的類(lèi),增加程序的復(fù)雜性
  • 動(dòng)態(tài)裝飾在多層裝飾時(shí)會(huì)更復(fù)雜

到此這篇關(guān)于Java經(jīng)典設(shè)計(jì)模式之裝飾器模式解析的文章就介紹到這了,更多相關(guān)Java裝飾器模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

  • Java刪除二叉搜索樹(shù)最大元素和最小元素的方法詳解

    Java刪除二叉搜索樹(shù)最大元素和最小元素的方法詳解

    這篇文章主要介紹了Java刪除二叉搜索樹(shù)最大元素和最小元素的方法,結(jié)合實(shí)例形式詳細(xì)分析了java針對(duì)二叉搜索樹(shù)的基本遍歷、查找、判斷、刪除等相關(guān)操作技巧,需要的朋友可以參考下
    2020-03-03
  • 使用Java實(shí)現(xiàn)一個(gè)能保留計(jì)算過(guò)程的計(jì)算器

    使用Java實(shí)現(xiàn)一個(gè)能保留計(jì)算過(guò)程的計(jì)算器

    計(jì)算器是我們?nèi)粘I钪谐S玫墓ぞ咧?它能夠進(jìn)行基本的數(shù)學(xué)運(yùn)算,如加法、減法、乘法和除法,而在設(shè)計(jì)一個(gè)計(jì)算器時(shí),我們可以通過(guò)使用Java編程語(yǔ)言來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的控制臺(tái)計(jì)算器,并且讓它能夠保留計(jì)算過(guò)程,文中有詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-11-11
  • SpringBoot如何訪(fǎng)問(wèn)html和js等靜態(tài)資源配置

    SpringBoot如何訪(fǎng)問(wèn)html和js等靜態(tài)資源配置

    這篇文章主要介紹了SpringBoot如何訪(fǎng)問(wèn)html和js等靜態(tài)資源配置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot實(shí)現(xiàn)異步事件驅(qū)動(dòng)的方法

    SpringBoot實(shí)現(xiàn)異步事件驅(qū)動(dòng)的方法

    本文主要介紹了SpringBoot實(shí)現(xiàn)異步事件驅(qū)動(dòng)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • JavaWeb表單注冊(cè)界面的實(shí)現(xiàn)方法

    JavaWeb表單注冊(cè)界面的實(shí)現(xiàn)方法

    這篇文章主要介紹了JavaWeb表單注冊(cè)界面的實(shí)現(xiàn)方法的相關(guān)資料,希望通過(guò)本文大家能掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • java實(shí)現(xiàn)推箱子小游戲

    java實(shí)現(xiàn)推箱子小游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)推箱子小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • 詳解簡(jiǎn)單基于spring的redis配置(單機(jī)和集群模式)

    詳解簡(jiǎn)單基于spring的redis配置(單機(jī)和集群模式)

    這篇文章主要介紹了詳解簡(jiǎn)單基于spring的redis配置(單機(jī)和集群模式),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • Mac使用Idea配置傳統(tǒng)SSM項(xiàng)目(非maven項(xiàng)目)

    Mac使用Idea配置傳統(tǒng)SSM項(xiàng)目(非maven項(xiàng)目)

    本文主要介紹了Mac使用Idea配置傳統(tǒng)SSM項(xiàng)目(非maven項(xiàng)目),將展示如何設(shè)置項(xiàng)目結(jié)構(gòu)、添加依賴(lài)關(guān)系等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Java設(shè)計(jì)模式中代理模式應(yīng)用詳解

    Java設(shè)計(jì)模式中代理模式應(yīng)用詳解

    代理模式(Proxy Parttern)為一個(gè)對(duì)象提供一個(gè)替身,來(lái)控制這個(gè)對(duì)象的訪(fǎng)問(wèn),即通過(guò)代理對(duì)象來(lái)訪(fǎng)問(wèn)目標(biāo)對(duì)象。本文將通過(guò)示例詳細(xì)講解一下這個(gè)模式,需要的可以參考一下
    2022-11-11
  • 最新評(píng)論

    徐州市| 华阴市| 嘉鱼县| 中牟县| 洪湖市| 宝丰县| 根河市| 涪陵区| 洛阳市| 东乡族自治县| 鹤峰县| 安远县| 教育| 定州市| 江山市| 普兰县| 江都市| 蕉岭县| 韶山市| 兴化市| 浮山县| 思茅市| 嘉荫县| 巩义市| 沂水县| 宝山区| 万全县| 盐池县| 左贡县| 阿坝县| 潮州市| 敖汉旗| 三原县| 许昌县| 凌源市| 金堂县| 固阳县| 高州市| 乌鲁木齐县| 余干县| 穆棱市|