欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java設(shè)計(jì)模式中的裝飾器模式簡(jiǎn)析

 更新時(shí)間:2023年12月01日 09:32:15   作者:MC-閏土  
這篇文章主要介紹了Java設(shè)計(jì)模式中的裝飾器模式簡(jiǎn)析,裝飾模式能夠?qū)崿F(xiàn)動(dòng)態(tài)的為對(duì)象添加功能,是從一個(gè)對(duì)象外部來(lái)給對(duì)象添加功能,通常給對(duì)象添加功能,要么直接修改對(duì)象添加相應(yīng)的功能,要么派生對(duì)應(yīng)的子類來(lái)擴(kuò)展,抑或是使用對(duì)象組合的方式,需要的朋友可以參考下

1. 什么是裝飾器模式

裝飾模式能夠?qū)崿F(xiàn)動(dòng)態(tài)的為對(duì)象添加功能,是從一個(gè)對(duì)象外部來(lái)給對(duì)象添加功能。通常給對(duì)象添加功能,要么直接修改對(duì)象添加相應(yīng)的功能,要么派生對(duì)應(yīng)的子類來(lái)擴(kuò)展,抑或是使用對(duì)象組合的方式。顯然,直接修改對(duì)應(yīng)的類這種方式并不可取。在面向?qū)ο蟮脑O(shè)計(jì)中,而我們也應(yīng)該盡量使用對(duì)象組合,而不是對(duì)象繼承來(lái)擴(kuò)展和復(fù)用功能。裝飾器模式就是基于對(duì)象組合的方式,可以很靈活的給對(duì)象添加所需要的功能。裝飾器模式的本質(zhì)就是動(dòng)態(tài)組合。動(dòng)態(tài)是手段,組合才是目的。總之,裝飾模式是通過(guò)把復(fù)雜的功能簡(jiǎn)單化,分散化,然后再運(yùn)行期間,根據(jù)需要來(lái)動(dòng)態(tài)組合的這樣一個(gè)模式。

注意上文說(shuō)的兩點(diǎn),簡(jiǎn)單化,動(dòng)態(tài)組合。

適用裝飾者模式場(chǎng)合:

1.當(dāng)我們需要為某個(gè)現(xiàn)有的對(duì)象,動(dòng)態(tài)的增加一個(gè)新的功能或職責(zé)時(shí),可以考慮使用裝飾模式。

2.當(dāng)某個(gè)對(duì)象的職責(zé)經(jīng)常發(fā)生變化或者經(jīng)常需要?jiǎng)討B(tài)的增加職責(zé),避免為了適應(yīng)這樣的變化,而增加繼承子類擴(kuò)展的方式,因?yàn)檫@種方式會(huì)造成子類膨脹的速度過(guò)快,難以控制。

簡(jiǎn)單來(lái)說(shuō),就是在添加功能的情況下,又不失靈活,比如上面說(shuō)到的生成Excel模板,如果以后想把鏈接頁(yè)放到內(nèi)容頁(yè)前面,那么只需要調(diào)整一下組合的順序,就可以實(shí)現(xiàn)了,不用把它的實(shí)現(xiàn)代碼大段地拷貝過(guò)去。

2.裝飾器的結(jié)構(gòu)

抽象構(gòu)件(component)角色 :這個(gè)角色用來(lái)規(guī)范被裝飾的對(duì)象,一般用接口方式給出。

具體構(gòu)件(concrete  component )角色 :被裝飾的類。

裝飾(decorator)角色 :持有一個(gè)構(gòu)件對(duì)象的實(shí)例。并定義一個(gè)跟抽象構(gòu)件一致的接口。

具體 (concrete    decorator   ) 裝飾角色 :負(fù)責(zé)給具體構(gòu)件添加附加職責(zé)的類。在實(shí)際使用中多數(shù)情況下裝飾角色和具體裝飾角色可能由一個(gè)類來(lái)承擔(dān)。

這個(gè)結(jié)構(gòu)中最關(guān)鍵的是,裝飾角色持有一個(gè)構(gòu)件對(duì)象的實(shí)例。這樣,需要裝飾的實(shí)例,才能夠傳入到裝飾器中,讓裝飾器對(duì)其進(jìn)行裝飾。同時(shí),在多個(gè)裝飾器共同裝飾的情況下,還可以把前面的裝飾器傳入到后面的裝飾器中,由最后的裝飾器調(diào)用動(dòng)作。因?yàn)樗鼈儗?shí)現(xiàn)了同樣的接口,這樣做是允許的。

例如:對(duì)象A,需要裝飾器A,B進(jìn)行裝飾。那么,可以把A傳給裝飾器A,裝飾后,再把A傳給裝飾器B,繼續(xù)裝飾。也可以把A傳給裝飾器A之后,再把裝飾器A傳給裝飾器B,由B完成所有的裝飾動(dòng)作(實(shí)際上只是調(diào)用了A的裝飾動(dòng)作,具體實(shí)現(xiàn)仍是在裝飾器A當(dāng)中)。

有同學(xué)可能會(huì)有疑問(wèn)了,使用裝飾器模式,要求被裝飾的類型必須和裝飾器的類型,實(shí)現(xiàn)相同的接口,具有相同的公有方法。對(duì)于已經(jīng)定義好的類型,怎么能做到裝飾呢?

比如上面說(shuō)的場(chǎng)景,對(duì)Excel文件進(jìn)行裝飾,一般我們使用POI的開源包,Excel文件對(duì)應(yīng)HSSFWorkBook類型,那么,是不是我們也要去實(shí)現(xiàn)HSSFWorkBook實(shí)現(xiàn)的接口WorkBook?那WorkBook接口里面沒(méi)有我們想要的裝飾方法聲明怎么辦?不就用不了了?

實(shí)際上這種場(chǎng)景,仍然可以使用裝飾器模式,方法就是將WorkBook類型封裝到具體構(gòu)件的角色里,并提供get方法。這樣裝飾器得到具體構(gòu)件后,就可以通過(guò)get方法獲取到真正需要裝飾的對(duì)象了(在下面的例子中,我將使用StringBuilder類型,原理是一樣的)

3. 一個(gè)小例子

嗯,是不是看懵逼了?沒(méi)關(guān)系,我們用上面的生成模板的場(chǎng)景,實(shí)踐一下。

首先,定義一個(gè)抽象構(gòu)件

package com.khlin.test;
/**
 * 模板文件類型。包裝了文件的內(nèi)容,{@link #fillContent()} 用于填充內(nèi)容
 * @author Kingsley
 *
 */
public interface TemplateFile {
    StringBuilder getContent();
    void fillContent();
}

定義具體構(gòu)件,即被裝飾的類

package com.khlin.test;
public class ImportTemplateFile implements TemplateFile {
    StringBuilder content = new StringBuilder();
    public ImportTemplateFile() {
        content.append("Title: this is an import template.");
    }
    @Override
    public StringBuilder getContent() {
        return this.content;
    }
    @Override
    public void fillContent() {
        System.out.println("ImportTemplateFile: i will do nothing.");
    }
}

第三步,定義一個(gè)裝飾器角色。通常是一個(gè)抽象類,同時(shí)持有第一步抽象構(gòu)件的一個(gè)實(shí)例,這是關(guān)鍵。

package com.khlin.test;
public abstract class FileDecorator implements TemplateFile {
    TemplateFile templateFile;
    public FileDecorator(TemplateFile templateFile) {
        this.templateFile = templateFile;
    }
}

最后一步,實(shí)現(xiàn)兩個(gè)具體的裝飾器

package com.khlin.test;
public class FileAutherDecorator extends FileDecorator {
    public FileAutherDecorator(TemplateFile templateFile) {
        super(templateFile);
    }
    @Override
    public StringBuilder getContent() {
        return this.templateFile.getContent();
    }
    @Override
    public void fillContent() {
        //先用上一個(gè)裝飾器處理,再用自己的邏輯處理
        this.templateFile.fillContent();
        StringBuilder content = this.templateFile.getContent();
        content.append("\r\nAuther: kingsley");
    }
}
package com.khlin.test;
import java.util.Date;
public class FileDateDecorator extends FileDecorator{
    public FileDateDecorator(TemplateFile templateFile) {
        super(templateFile);
    }
    @Override
    public StringBuilder getContent() {
        return templateFile.getContent();
    }
    @Override
    public void fillContent() {
        //先用上一個(gè)裝飾器處理,再用自己的邏輯處理
        this.templateFile.fillContent();
        StringBuilder content = this.templateFile.getContent();
        content.append("\r\nDate: " + new Date(System.currentTimeMillis()));
    }
}

最后,我們來(lái)運(yùn)行一下

 package com.khlin.test;
  public class App {
      public static void main(String[] args) {
          TemplateFile file = new ImportTemplateFile();
          // 把要裝飾的對(duì)象傳給裝飾器
          TemplateFile dateDecorator = new FileDateDecorator(file);
         /**
          * 這里可以有兩種做法。
          * 第一種是先調(diào)用dateDecorator.fillContent(),先進(jìn)行裝飾,然后再把file傳給autherDecorator
          * ,由它繼續(xù)裝飾。 第二種是把dateDecorator作為參數(shù)傳給autherDecorator,由后者一次性地全部裝飾。
          * 這里采用第二種。選用這種,要保證在裝飾器的裝飾方法里面,顯式地調(diào)用傳入?yún)?shù)的裝飾方法。
          */
         TemplateFile autherDecorator = new FileAutherDecorator(dateDecorator);
         autherDecorator.fillContent();
         System.out.println(autherDecorator.getContent());
     }
 }

實(shí)例:

漢堡基類

package decorator;
 
public abstract class Humburger {
	
	protected  String name ;
	
	public String getName(){
		return name;
	}
	
	public abstract double getPrice();
 
}

雞腿堡類

package decorator;
 
public class ChickenBurger extends Humburger {
	
	public ChickenBurger(){
		name = "雞腿堡";
	}
 
	@Override
	public double getPrice() {
		return 10;
	}
 
}

配料的基類

package decorator;
 
public abstract class Condiment extends Humburger {
	
	public abstract String getName();
 
}

生菜

package decorator;
 
public class Lettuce extends Condiment {
	
	Humburger humburger;
	
	public Lettuce(Humburger humburger){
		this.humburger = humburger;
	}
 
	@Override
	public String getName() {
		return humburger.getName()+" 加生菜";
	}
 
	@Override
	public double getPrice() {
		return humburger.getPrice()+1.5;
	}
 
}

辣椒

package decorator;
 
public class Chilli extends Condiment {
	
	Humburger humburger;
	
	public Chilli(Humburger humburger){
		this.humburger = humburger;
		
	}
 
	@Override
	public String getName() {
		return humburger.getName()+" 加辣椒";
	}
 
	@Override
	public double getPrice() {
		return humburger.getPrice();  //辣椒是免費(fèi)的哦
	}
 
}

測(cè)試

package decorator;
 
public class Test {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Humburger humburger = new ChickenBurger();
		System.out.println(humburger.getName()+"  價(jià)錢:"+humburger.getPrice());
		Lettuce lettuce = new Lettuce(humburger);
		System.out.println(lettuce.getName()+"  價(jià)錢:"+lettuce.getPrice());
		Chilli chilli = new Chilli(humburger);
		System.out.println(chilli.getName()+"  價(jià)錢:"+chilli.getPrice());
		Chilli chilli2 = new Chilli(lettuce);
		System.out.println(chilli2.getName()+"  價(jià)錢:"+chilli2.getPrice());
	}
 
}

輸出

雞腿堡  價(jià)錢:10.0
雞腿堡 加生菜  價(jià)錢:11.5
雞腿堡 加辣椒  價(jià)錢:10.0
雞腿堡 加生菜 加辣椒  價(jià)錢:11.5

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

相關(guān)文章

  • java返回json請(qǐng)求中文變成問(wèn)號(hào)的問(wèn)題及解決

    java返回json請(qǐng)求中文變成問(wèn)號(hào)的問(wèn)題及解決

    這篇文章主要介紹了java返回json請(qǐng)求中文變成問(wèn)號(hào)的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Jmeter常見(jiàn)函數(shù)使用方法匯總

    Jmeter常見(jiàn)函數(shù)使用方法匯總

    這篇文章主要介紹了Jmeter函數(shù)使用方法匯總,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • JavaSE文件操作工具類FileUtil詳解

    JavaSE文件操作工具類FileUtil詳解

    這篇文章主要為大家詳細(xì)介紹了JavaSE系列之文件操作工具類FileUtil,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • java如何實(shí)現(xiàn)數(shù)位分離

    java如何實(shí)現(xiàn)數(shù)位分離

    這篇文章主要介紹了java如何實(shí)現(xiàn)數(shù)位分離,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Spring Boot 整合 JWT的方法

    Spring Boot 整合 JWT的方法

    這篇文章主要介紹了Spring Boot 整合 JWT的方法,文中實(shí)例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 優(yōu)雅地在Java 8中處理異常的方法詳解

    優(yōu)雅地在Java 8中處理異常的方法詳解

    異常處理是我們?cè)谌粘i_發(fā)中經(jīng)常會(huì)遇到的一種需求,下面這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅地在Java 8中處理異常的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們來(lái)一起看看吧
    2019-01-01
  • 設(shè)計(jì)模式系列之組合模式及其在JDK和MyBatis源碼中的運(yùn)用詳解

    設(shè)計(jì)模式系列之組合模式及其在JDK和MyBatis源碼中的運(yùn)用詳解

    這篇文章主要介紹了組合模式及其在JDK和MyBatis源碼中的運(yùn)用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Spring Cloud服務(wù)入口Gateway的介紹和使用問(wèn)題小結(jié)

    Spring Cloud服務(wù)入口Gateway的介紹和使用問(wèn)題小結(jié)

    Spring Cloud Gateway是Spring Cloud的?個(gè)全新的API?關(guān)項(xiàng)?, 基于Spring + SpringBoot等技術(shù)開發(fā), ?的是為了替換掉Zuul,這篇文章主要介紹了Spring Cloud服務(wù)入口Gateway的介紹和使用問(wèn)題小結(jié),需要的朋友可以參考下
    2025-03-03
  • java發(fā)送email一般步驟(實(shí)例講解)

    java發(fā)送email一般步驟(實(shí)例講解)

    下面小編就為大家?guī)?lái)一篇java發(fā)送email一般步驟(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • IntelliJ IDEA 刷題利器 LeetCode 插件詳解

    IntelliJ IDEA 刷題利器 LeetCode 插件詳解

    這篇文章主要介紹了IntelliJ IDEA 刷題利器 LeetCode 插件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08

最新評(píng)論