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

詳解Java如何優(yōu)雅的使用裝飾器模式

 更新時間:2022年09月14日 08:27:19   作者:指北君  
裝飾器設(shè)計(jì)模式大家肯定都聽說過,但是有沒有使用過呢,今天本君就跟大家分享一下裝飾器模式應(yīng)該如何使用,感興趣的小伙伴可以學(xué)習(xí)一下

什么是裝飾器模式

裝飾器模式(Decorator Pattern): 在不改變對象自身的基礎(chǔ)上,在程序運(yùn)行期間給對象動態(tài)的添加職責(zé);

感覺和繼承如出一轍,不改變父類,子類可拓展功能;

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

裝飾類和被裝飾類可以獨(dú)立發(fā)展,不會相互耦合

相比于繼承,更加的輕便、靈活

可以動態(tài)擴(kuò)展一個實(shí)現(xiàn)類的功能,不必修改原本代碼

缺點(diǎn)

會產(chǎn)生很多的裝飾類,增加了系統(tǒng)的復(fù)雜性。

這種比繼承更加靈活機(jī)動的特性,也同時意味著裝飾模式比繼承易于出錯,排錯也很困難,對于多次裝飾的對象,調(diào)試時尋找錯誤可能需要逐級排查,較為繁瑣。

使用場景

對已有的目標(biāo)功能存在不足,需要增強(qiáng)時,擴(kuò)展類的功能。

動態(tài)增加功能,動態(tài)撤銷

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

代理是全權(quán)代理,目標(biāo)根本不對外,全部由代理類來完成;裝飾是增強(qiáng),是輔助,目標(biāo)仍然可以自行對外提供服務(wù),裝飾器只起增強(qiáng)作用。

裝飾器模式強(qiáng)調(diào)的是:增強(qiáng)、新增行為;代理模式強(qiáng)調(diào)的是:對代理的對象施加控制,但不對對象本身的功能進(jìn)行增強(qiáng)。

裝飾器模式:生效的對象還是原本的對象;代理模式:生效的是新的對象(代理對象)

裝飾器和代理的區(qū)別

裝飾器的簡單實(shí)現(xiàn)

場景:天氣太熱了,喝點(diǎn)兒冰水解解暑;加點(diǎn)兒檸檬片,讓果汁好喝點(diǎn)兒

先定義一個喝水的接口

public?interface?Drink?{
????/**
?????*?喝水
?????*/
????void?drink();
}

寫一個接口的實(shí)現(xiàn)

public?class?DrinkWater?implements?Drink?{

????@Override
????public?void?drink()?{
????????System.out.println("喝水");
????}

}

一個簡單的裝飾器

public?class?DrinkDecorator?implements?Drink?{

????private?final?Drink?drink;

????public?DrinkDecorator(Drink?drink)?{
????????this.drink?=?drink;
????}

????@Override
????public?void?drink()?{
????????System.out.println("先加點(diǎn)兒檸檬片");
????????drink.drink();
????}

}

開始測試

public?class?DrinkMain?{
????public?static?void?main(String[]?args)?{
????????Drink?drink?=?new?DrinkWater();
????????drink?=?new?DrinkDecorator(drink);
????????drink.drink();
????}
}

運(yùn)行結(jié)果

先加點(diǎn)兒檸檬片
喝水

一個簡單的裝飾器模式例子就寫完了;當(dāng)然這種例子在實(shí)際項(xiàng)目中肯定是用不到的,這里只是先了解一下裝飾器模式

裝飾器模式實(shí)戰(zhàn)

場景: 項(xiàng)目一期開發(fā)的時候,并沒有給鑒權(quán)部分設(shè)置緩存;二期開發(fā)考慮到性能問題,想要給鑒權(quán)部分加上緩存,這里就選擇了使用裝飾器模式進(jìn)行處理;

這里使用的緩存是spring的 spring-cache,不了解沒關(guān)系,知道幾個注解什么意思就行

@Cacheable 表示要對方法返回值進(jìn)行緩存

@CacheEvict 刪除緩存注解

為了簡潔,以下代碼均為偽代碼

首先,需要一個權(quán)限的接口和實(shí)現(xiàn)類

public?interface?IDataAccessor?{
????/**
?????*?根據(jù)部門上級?id?獲取所有子集部門
?????*/
????Set<Long>?deptFindAllChildrenByParentIds(Collection<Long>?parentIds);

????/**
?????*?獲取數(shù)據(jù)范圍內(nèi)的部門
?????*/
????Set<Long>?deptFindScopeById(Long?userId);

實(shí)現(xiàn)類(注意這里加了@Service, 交給spring處理)

@Service
public?class?ScopeDataAccessorImpl?implements?IDataAccessor?{
????@Autowired
????private?IDepartmentService?departmentService;
????
????@Autowired
????private?INodeScopeService?nodeScopeService;

????@Override
????public?Set<Long>?deptFindAllChildrenByParentIds(Collection<Long>?parentIds)?{
????????Set<Long>?result?=?new?HashSet<>();
????????departmentService.departmentChildren(parentIds,?result);
????????return?result;
????}
????
????@Override
????public?Set<Long>?deptFindScopeById(Long?userId)?{
????????return?nodeScopeService.deptFindScopeById(userId);
????}
}

接下來就是對之前的代碼進(jìn)行裝飾,定義一個裝飾器的實(shí)現(xiàn)類

(這個類沒有 @Component, 沒有直接交給spring管理;加了注解會報錯:找到了2個bean)

public?class?DataAccessorDecorator?implements?IDataAccessor?{
????private?final?IDataAccessor?iDataAccessor;

????public?DataAccessorDecorator(IDataAccessor?iDataAccessor)?{
????????this.iDataAccessor?=?iDataAccessor;
????}

????@Cacheable(cacheNames?=?"dept:parentId",?key?=?"#p0",?sync?=?true)
????@Override
????public?Set<Long>?deptFindAllChildrenByParentIds(Collection<Long>?parentIds)?{
????????return?iDataAccessor.deptFindAllChildrenByParentIds(parentIds);
????}

????@Cacheable(cacheNames?=?"dept:scope:userId",?key?=?"#p0",?sync?=?true)
????@Override
????public?Set<Long>?deptFindScopeById(Long?userId)?{
????????return?iDataAccessor.deptFindScopeById(nodeId,userId);
????}
}

接下來還需要將這個裝飾器的類注冊到spring中

@Configuration
@ConditionalOnBean({IDataAccessor.class})
public?class?Config?{
????
????@Bean
????@ConditionalOnBean({IDataAccessor.class})
????public?DataAccessorDecorator?dataAccessorDecorator(IDataAccessor?iDataAccessor)?{
????????return?new?DataAccessorDecorator(iDataAccessor);
????}
}

根據(jù)業(yè)務(wù),維護(hù)緩存更新;這里使用的監(jiān)聽部門和員工的變更事件

@Component
public?class?DataScopeEvict?{

????/**
?????*?清空部門相關(guān)緩存
?????*/
????@CacheEvict(cacheNames?=?{"dept:parentId"},?allEntries?=?true)
????public?void?department()?{
????}

????/**
?????*?清空用戶相關(guān)緩存
?????*/
????@CacheEvict(cacheNames?=?{"dept:scope:userId"},?allEntries?=?true)
????public?void?user()?{
????}
}
@Component
public?class?ScopeDataEventListener?{
????@Autowired
????private?DataScopeEvict?evict;
????
?/**
?????*?監(jiān)聽部門變更事件
?????*/
????@EventListener
????public?void?departmentEvent(DepartmentChangeEvent?event)?{
????????//?1?增加?2?刪除?3?上級部門變更
????????evict.department();
????}

????/**
?????*?監(jiān)聽user變更事件
?????*/
????@EventListener
????public?void?userEvent(UserChangeEvent?event)?{
????????//?2?刪除?3?主部門變更
????????if?(event.getType().equals(2)?||?event.getType().equals(3))?{
????????????evict.user();
????????}
????}
}

一切準(zhǔn)備就緒,使用的時候直接使用裝飾器類就好了

@Service
public?class?UserService?{
????
????@Autowired
????DataAccessorDecorator?scopeDataAccessor;

????
????public?Set<Long>?deptFindAllChildrenByParentIds(Collection<Long>?parentIds)?{
????????return?scopeDataAccessor.deptFindAllChildrenByParentIds(parentIds);
????}
????
????
????public?Set<Long>?deptFindScopeById(Long?userId)?{
????????return?scopeDataAccessor.deptFindScopeById(userId);
????}
????
}

以上就是一個將裝飾器模式應(yīng)用到實(shí)際項(xiàng)目的例子;

在這個例子中,使用裝飾器模式增強(qiáng)了原本的代碼,不修改原本的代碼,原本的代碼也能正確提供服務(wù),只不過沒有使用緩存;只要方法名命名一致,只需修改注入的字段就可以升級完成,升級成本還是很低的。

這波使用裝飾器模式加緩存的操作寫到項(xiàng)目中,直接讓你的代碼 B ge pull full

小結(jié)

雖然使用裝飾器模式看起來B格高,但還是要注意自己項(xiàng)目的場景,選擇適合的方式解決問題。

以上就是詳解Java如何優(yōu)雅的使用裝飾器模式的詳細(xì)內(nèi)容,更多關(guān)于Java裝飾器模式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot中的FailureAnalyzer使用詳解

    SpringBoot中的FailureAnalyzer使用詳解

    這篇文章主要介紹了SpringBoot中的FailureAnalyzer使用詳解,Spring Boot的FailureAnalyzer是一個接口,它用于在Spring Boot應(yīng)用啟動失敗時提供有關(guān)錯誤的詳細(xì)信息,這對于開發(fā)者來說非常有用,因?yàn)樗梢詭椭覀兛焖僮R別問題并找到解決方案,需要的朋友可以參考下
    2023-12-12
  • springboot跨域過濾器fetch react Response to preflight request doesn‘t pass access control check問題

    springboot跨域過濾器fetch react Response to p

    這篇文章主要介紹了springboot跨域過濾器fetch react Response to preflight request doesn‘t pass access control check問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Java實(shí)題演練二叉搜索樹與雙向鏈表分析

    Java實(shí)題演練二叉搜索樹與雙向鏈表分析

    這篇文章主要介紹了Java二叉搜索樹與雙向鏈表,總的來說這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達(dá)的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路
    2022-12-12
  • java?hutool工具類處理JSON的使用方法

    java?hutool工具類處理JSON的使用方法

    hutool是一個java基礎(chǔ)工具類,該工具類經(jīng)過長期的發(fā)展,API已經(jīng)非常齊全,下面這篇文章主要給大家介紹了關(guān)于java?hutool工具類處理JSON的使用方法,需要的朋友可以參考下
    2024-04-04
  • Spring?BeanDefinition父子關(guān)系示例解析

    Spring?BeanDefinition父子關(guān)系示例解析

    這篇文章主要為大家介紹了Spring?BeanDefinition父子關(guān)系示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java依賴倒轉(zhuǎn)原則_動力節(jié)點(diǎn)Java學(xué)院整理

    Java依賴倒轉(zhuǎn)原則_動力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java依賴倒轉(zhuǎn)原則的定義及問題由來解決方案,感興趣的朋友一起看看吧
    2017-08-08
  • java?使用BeanFactory實(shí)現(xiàn)service與dao層解耦合詳解

    java?使用BeanFactory實(shí)現(xiàn)service與dao層解耦合詳解

    這篇文章主要介紹了java?使用BeanFactory實(shí)現(xiàn)service與dao層解耦合詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java調(diào)用構(gòu)造函數(shù)和方法及使用詳解

    Java調(diào)用構(gòu)造函數(shù)和方法及使用詳解

    在Java編程中,構(gòu)造函數(shù)用于初始化新創(chuàng)建的對象,而方法則用于執(zhí)行對象的行為,構(gòu)造函數(shù)在使用new關(guān)鍵字創(chuàng)建類實(shí)例時自動調(diào)用,沒有返回類型,并且名稱與類名相同,本文通過示例詳細(xì)介紹了如何在Java中使用構(gòu)造函數(shù)和方法,感興趣的朋友一起看看吧
    2024-10-10
  • linux下執(zhí)行java程序的sh腳本分享

    linux下執(zhí)行java程序的sh腳本分享

    這篇文章主要介紹了linux下執(zhí)行java程序的sh腳本,僅供參考,但是設(shè)置的時候環(huán)境變量是最重要的,我就是環(huán)境變量一直不對,總是按網(wǎng)上查到的來,不明白怎么回事,才一直出錯,其實(shí)環(huán)境變量就是你要執(zhí)行的java程序所在的位置
    2014-09-09
  • Java編寫簡單計(jì)算器的完整實(shí)現(xiàn)過程

    Java編寫簡單計(jì)算器的完整實(shí)現(xiàn)過程

    這篇文章主要給大家介紹了關(guān)于Java編寫簡單計(jì)算器的完整實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評論

封丘县| 四平市| 霍山县| 许昌市| 新平| 盐津县| 广饶县| 霍山县| 曲阳县| 申扎县| 绥阳县| 信丰县| 余江县| 新昌县| 英山县| 新河县| 邓州市| 临朐县| 辛集市| 青浦区| 惠东县| 白银市| 许昌市| 炎陵县| 肇东市| 辽阳县| 湖州市| 克山县| 怀安县| 韩城市| 邛崃市| 玉溪市| 自贡市| 沧州市| 保靖县| 武城县| 吉木乃县| 秦安县| 原阳县| 六枝特区| 云和县|