日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java模式之装饰器模式

發(fā)布時(shí)間:2023/12/29 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java模式之装饰器模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

定義:

裝飾器模式也叫作包裝器模式,只在不改變?cè)袑?duì)象的基礎(chǔ)上,動(dòng)態(tài)的給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來(lái)說(shuō),裝飾器模式相比生成子類更為靈活,屬于結(jié)構(gòu)型設(shè)計(jì)模式

裝飾器模式提供了比繼承更有彈性的替代方案將功能附加到對(duì)象上。因此,裝飾器模式的核心功能是功能擴(kuò)展,使用裝飾器模式可以透明且動(dòng)態(tài)的擴(kuò)展類的功能

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

  • 用于擴(kuò)展一個(gè)類的功能,或者給一個(gè)類添加附加職責(zé)

  • 動(dòng)態(tài)的給一個(gè)對(duì)象添加功能,這些功能可以再動(dòng)態(tài)的被撤銷

  • 需要為一批平行的兄弟類進(jìn)行改裝或者加裝功能

  • UML類圖:

    ?

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

  • 抽象組建(Component):可以是一個(gè)接口或者抽象類,充當(dāng)被裝飾類的原始對(duì)象,規(guī)定了被裝飾對(duì)象的行為

  • 具體組件(ConcreteComponent):實(shí)現(xiàn)/繼承Component的一個(gè)具體對(duì)象,即被裝飾對(duì)象

  • 抽象裝飾器(Decorator):通用的裝飾ConcreteComponent的裝飾器,其內(nèi)部必然有一個(gè)屬性指向Component,其實(shí)現(xiàn)一般是一個(gè)抽象類,主要為了讓其子類按照其構(gòu)造形式傳入一個(gè)Component,這是強(qiáng)制的通用行為。如果系統(tǒng)中裝飾邏輯單一,則并不需要實(shí)現(xiàn)許多裝飾器,可以直接省略該類,而直接實(shí)現(xiàn)一個(gè)具體裝飾器即可

  • 具體裝飾器(ConcreteDecorator):Decorator的具體實(shí)現(xiàn)類,理論上,每個(gè)ConcreteDecorator都擴(kuò)展了Component對(duì)象的一種功能

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

    通用寫法:

    package com.design.pattern.decorator; ? 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{ ?@Overridepublic 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類

    package com.design.pattern.decorator; ? public class Battercake {protected String getMsg(){return "煎餅";}public int getPrice(){return 5;} }

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

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

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

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

    最后編寫客戶端測(cè)試代碼

    package com.design.pattern.decorator; ? 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)題。但是,如果用戶需要一個(gè)加2個(gè)雞蛋和1根香腸的煎餅,則用現(xiàn)在的類結(jié)構(gòu)是創(chuàng)建不出來(lái)的,也無(wú)法自動(dòng)計(jì)算出價(jià)格,除非再創(chuàng)建一個(gè)類做定制。如果需求在變,那么一直加定制顯然是不科學(xué)的

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

    package com.design.pattern.decorator.base; ? public abstract class Battercake {protected abstract String getMsg();protected abstract int getPrice(); }

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

    package com.design.pattern.decorator.base; ? public class BaseBattercake extends Battercake{@Overrideprotected String getMsg() {return "煎餅";}@Overrideprotected int getPrice() {return 5;} }

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

    package com.design.pattern.decorator.base; ? 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

    package com.design.pattern.decorator.base; ? public class EggDecorator extends BattercakeDecotator{public EggDecorator(Battercake battercake) {super(battercake);} ?@Overrideprotected void doSomething() {}protected String getMsg(){return super.getMsg() + "+1個(gè)雞蛋";}protected int getPrice(){return super.getPrice() + 1;} }

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

    package com.design.pattern.decorator.base; ? public class SausageDecorator extends BattercakeDecotator{public SausageDecorator(Battercake battercake) {super(battercake);}@Overrideprotected void doSomething() {}protected String getMsg(){return super.getMsg() + "+1根香腸";}protected int getPrice(){return super.getPrice() + 2;} }

    在編寫客戶端測(cè)試代碼

    package com.design.pattern.decorator.base; ? public class Client {public static void main(String[] args) {//買一個(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類圖和通用代碼實(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,著重類功能的變化。

    代理模式強(qiáng)調(diào)對(duì)代理過(guò)程的控制。Proxy完全掌握對(duì)RealSubject的訪問(wèn)控制,因此,Proxy可以決定對(duì)RealSubject進(jìn)行功能擴(kuò)展,功能縮減甚至功能散失,主體對(duì)象為Proxy。

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

  • 裝飾器是繼承的有力補(bǔ)充,比繼承靈活,在不改變?cè)袑?duì)象的情況下,動(dòng)態(tài)地給一個(gè)對(duì)象擴(kuò)展功能,即插即用。

  • 通過(guò)使用不同裝飾類及這些裝飾類的排列組合,可以實(shí)現(xiàn)不同效果

  • 裝飾器模式完全遵守開閉原則

  • 缺點(diǎn):

  • 會(huì)出現(xiàn)更多的代碼,更多的類,增加程序的復(fù)雜性

  • 動(dòng)態(tài)裝飾在多層裝飾時(shí)會(huì)更復(fù)雜

  • 總結(jié)

    以上是生活随笔為你收集整理的java模式之装饰器模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。