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

Java設(shè)計模式之裝飾模式詳解

 更新時間:2022年07月27日 09:20:17   作者:kaico2018  
這篇文章主要介紹了Java設(shè)計模式中的裝飾者模式,裝飾者模式即Decorator?Pattern,裝飾模式是在不必改變原類文件和使用繼承的情況下,動態(tài)地擴展一個對象的功能,裝飾模式又名包裝模式。裝飾器模式以對客戶端透明的方式拓展對象的功能,是繼承關(guān)系的一種替代方案

多級緩存

在實際開發(fā)項目,為了減少數(shù)據(jù)庫的訪問壓力,都會將數(shù)據(jù)緩存到內(nèi)存中

比如:Redis(分布式緩存)、EHCHE(JVM內(nèi)置緩存).

例如在早期中,項目比較小可能不會使用Redis做為緩存,使用JVM內(nèi)置的緩存框架,項目比較大的時候開始采用Redis分布式緩存框架,這時候需要設(shè)計一級與二級緩存。

緩存機制

1、JVM內(nèi)置緩存:將數(shù)據(jù)緩存在當前的jvm中,缺陷:占用我們的JVM內(nèi)存,存在內(nèi)存溢出問題,集群很難保證各個節(jié)點之間數(shù)據(jù)同步問題。

2、分布式緩存:Redis,數(shù)據(jù)可以集群共享

裝飾模式

不改變原有代碼的基礎(chǔ)之上,新增附加功能 ,mybatis、hibernate的二級緩存都屬于開發(fā)者自己去擴展功能。

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

裝飾模式對我們的裝飾對象實現(xiàn)增強,而代理模式及對我們目標對象實現(xiàn)增強。

類圖

  • Component (抽象構(gòu)件)

抽象構(gòu)件它是具體構(gòu)件和抽象裝飾類的共同父類,聲明了在具體構(gòu)件中實現(xiàn)的業(yè)務(wù)方法。

  • ConcreteComponent (具體構(gòu)件 [被裝飾類] )

具體構(gòu)件ConcreteComponent是最核心、最原始、最基本的接口或抽象類的實現(xiàn),要裝飾的就是它。

  • Decorator (抽象裝飾類)

抽象裝飾類也是抽象構(gòu)件類的子類,用于給具體構(gòu)件增加職責(zé),但是具體職責(zé)在其子類中實現(xiàn)。它維護一個指向抽象構(gòu)件對象的引用,通過該引用可以調(diào)用裝飾之前構(gòu)件對象的方法,并通過其子類擴展該方法,以達到裝飾的目的。

  • ConcreteDecorator ( 具體裝飾類)

具體裝飾類是抽象裝飾類的子類,負責(zé)向構(gòu)件添加新的職責(zé)。每一個具體裝飾類都定義了一些新的行為,它可以調(diào)用在抽象裝飾類中定義的方法,并可以增加新的方法用以擴充對象的行為。

實現(xiàn)裝飾器模式思路:

使用場景

  • 需要擴展一個類的功能時
  • 需要動態(tài)地給一個對象增加功能,并可以動態(tài)地撤銷時
  • 需要為一批的兄弟類進行改裝或加裝功能時

優(yōu)缺點

優(yōu)點

  • 裝飾類和被裝飾類可以獨立發(fā)展,而不會相互耦合。它有效地把類的核心職責(zé)和裝飾功能分開了
  • 裝飾模式是繼承關(guān)系的一一個替代方案。我們看裝飾類Decorator,不管裝飾多少層,返回的對象還是Component,實現(xiàn)的還是is-a的關(guān)系。
  • 裝飾模式可以動態(tài)地擴展一個實現(xiàn)類的功能

缺點

  • 使用裝飾模式進行系統(tǒng)設(shè)計時將產(chǎn)生很多小對象,這些對象的區(qū)別在于它們之間相互連接的方式有所不同,而不是它們的類或者屬性值有所不同,大量小對象的產(chǎn)生勢必會占用更多的系統(tǒng)資源,在-定程序上影響程序的性能。
  • 裝飾模式提供了一種比繼承更加靈活機動的解決方案,但同時也意味著比繼承更加易于出錯,排錯也很困難,對于多次裝飾的對象,調(diào)試時尋找錯誤可能需要逐級排查,較為繁瑣。

實現(xiàn)邏輯

裝飾者類內(nèi)部含有被裝飾者(組合關(guān)系),且被裝飾者與裝飾者都繼承自共同的父類。這樣可以通過將被裝飾者的子類實例對象 傳入-> 裝飾者子類的實例對象中,拓展被裝飾者繼承類即可實現(xiàn)動態(tài)的將新功能 附加到裝飾者子類實例對象上。在對象功能擴展方面,它比繼承更有彈性,裝飾者模式也體現(xiàn)了開閉原則(ocp)。

使用裝飾模式實現(xiàn)二級緩存

設(shè)計思路

代碼案例

1、準備兩個工具類(jvm緩存和redis緩存)

public class JvmMapCacheUtils {
    /**
     * 緩存容器
     */
    private static Map<String, String> caches = new ConcurrentHashMap<>();
    public static  <T> T getEntity(String key, Class<T> t) {
        // 緩存存放對象的情況
        String json = caches.get(key);
        return JSONObject.parseObject(json, t);
    }
    public static void putEntity(String key, Object o) {
        String json = JSONObject.toJSONString(o);
        caches.put(key, json);
    }
}
@Component
public class RedisUtils {
    private final Map<String, String> map = new ConcurrentHashMap<>();
    /**
     * 存放string類型
     *
     * @param key     key
     * @param data    數(shù)據(jù)
     */
    public void setString(String key, String data) {
        map.put(key, data);
    }
    /**
     * 根據(jù)key查詢string類型
     *
     * @param key
     * @return
     */
    public String getString(String key) {
        String value = map.get(key);
        return value;
    }
    public <T> T getEntity(String key, Class<T> t) {
        String json = getString(key);
        return JSONObject.parseObject(json, t);
    }
    public void putEntity(String key, Object object) {
        String json = JSONObject.toJSONString(object);
        setString(key, json);
    }
    /**
     * 根據(jù)對應(yīng)的key刪除key
     *
     * @param key
     */
    public void delKey(String key) {
        map.put(key, null);
    }
}

2、編寫緩存接口和裝飾者抽象類(抽象構(gòu)件),抽象類繼承接口

public interface ComponentCache {
    /**
     * 根據(jù)key查詢緩存數(shù)據(jù)
     *
     * @param
     * @return
     */
    <T> T getCacheEntity(String key, Class<T> t);
}
public interface AbstractDecorate extends  ComponentCache {
}

3、編寫jvm緩存(具體構(gòu)件)也是一級緩存

userMapper.findByUser(1):這里查詢數(shù)據(jù)庫的代碼就不提供。

@Component
public class JvmComponentCache implements ComponentCache {
    @Autowired
    private UserMapper userMapper;
    /**
     * @param key
     * @param t         返回的數(shù)據(jù)類型
     * @param joinPoint
     * @return T
     * @Author kaico
     * @Description //TODO
     * @Date 21:02 2022/7/5
     * @Param
     */
    @Override
    public <T> T getCacheEntity(String key, Class<T> t, ProceedingJoinPoint joinPoint) {
        // 先查詢我們的一級緩存(Jvm內(nèi)置)
        T jvmUser = JvmMapCacheUtils.getEntity(key,t);
        if (jvmUser != null) {
            return (T) jvmUser;
        }
//          查詢我們的db 通過aop直接獲取到我們的目標對象方法
        try {
            Object resultDb = joinPoint.proceed();
            // 數(shù)據(jù)庫DB有的情況 將該內(nèi)容緩存到當前Jvm中
            JvmMapCacheUtils.putEntity(key, resultDb);
            return (T) resultDb;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }
    }
    /**
     * @Author kaico
     * @Description //TODO 直接查詢數(shù)據(jù)庫查詢數(shù)據(jù)
     * @Date 8:02 2022/7/6
     */
    @Override
    public <T> T getCacheEntity(String key, Class<T> t ) {
        // 先查詢我們的一級緩存(Jvm內(nèi)置)
        T jvmUser = JvmMapCacheUtils.getEntity(key,t);
        if (jvmUser != null) {
            return (T) jvmUser;
        }
        // 查詢我們的db 通過aop直接獲取到我們的目標對象方法
        UserEntity byUser = userMapper.findByUser(1);
        if(byUser == null){
            return null;
        }
        // 數(shù)據(jù)庫DB有的情況 將該內(nèi)容緩存到當前Jvm中
        JvmMapCacheUtils.putEntity(key, byUser);
        return (T) byUser;
    }
}

4、編寫redis二級緩存(這里使用繼承的方式)

@Component
public class RedisDecorate extends JvmComponentCache implements AbstractDecorate {
    @Autowired
    private RedisUtils redisUtils;
    @Override
    public <T> T getCacheEntity(String key, Class<T> t, ProceedingJoinPoint joinPoint) {
        // 查詢我們的二級緩存
        // 先查詢二級緩存
        T redisUser = redisUtils.getEntity(key, t);
        if (redisUser != null) {
            return (T) redisUser;
        }
        // 如果一級緩存存在數(shù)據(jù)
        T jvmUser = super.getCacheEntity(key, t, joinPoint);
        if (jvmUser == null) {
            return null;
        }
        // 將該緩存數(shù)據(jù)放入到二級緩存中
        redisUtils.putEntity(key, jvmUser);
        return (T) jvmUser;
    }
}

5、使用裝飾過后的緩存類

@Component
public class KaicoCache {
    @Autowired
    private RedisDecorate redisDecorate;
    public <T> T getCacheEntity(String key, Class<T> t, ProceedingJoinPoint joinPoint) {
        return redisDecorate.getCacheEntity(key, t, joinPoint);
    }
}

分析Java的jdk中的裝飾器模式

以下是Java I/O流InputStream的部分類圖

通過圖中可以看出:

  • 抽象構(gòu)件(Component)角色:由InputStream扮演。這是-個抽象類,為各種子類型提供統(tǒng)一的接口。
  • 具體構(gòu)件(ConcreteComponent)角色:由ByteArrayInputStream、 FilelnputStream、 PipedInputStream、StringBufferlnputStream等類扮演。它們實現(xiàn)了抽象構(gòu)件角色所規(guī)定的接口。
  • 抽象裝飾(Decorator)角色:由FilterInputStream扮演。它實現(xiàn)了InputStream所規(guī)定的接口。
  • 具體裝飾(ConcreteDecorator)角色:由幾個類扮演,分別是BufferedInputStream、DatalnputStream以及 兩個不常用到的類LineNumberlnputStream、PushbackInputStream。

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

相關(guān)文章

  • 比較常用UML類圖幾種關(guān)系的小結(jié)

    比較常用UML類圖幾種關(guān)系的小結(jié)

    本文給大家總結(jié)了UML類圖中幾種比較常用的關(guān)系小總結(jié),需要的朋友可以參考下
    2015-10-10
  • idea搭建SSM框架遇踩的坑(附完整過程)

    idea搭建SSM框架遇踩的坑(附完整過程)

    最近準備搭建一個SSM框架,由于很久沒有搭建了,一來就遇到各種問題,折騰了一天終于搞定了,特此記錄一下遇到的問題,下面這篇文章主要給大家介紹了關(guān)于idea搭建SSM框架遇踩的坑,文中還附完整過程,需要的朋友可以參考下
    2023-04-04
  • Java實現(xiàn)兩個隨機數(shù)組合并進行排序的方法

    Java實現(xiàn)兩個隨機數(shù)組合并進行排序的方法

    本文主要介紹了Java實現(xiàn)兩個隨機數(shù)組合并進行排序的方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Java修飾符 abstract,static,final 的區(qū)別詳解

    Java修飾符 abstract,static,final 的區(qū)別詳解

    以下是對Java修飾符abstract,static,final的區(qū)別進行了詳細的介紹,需要的朋友可以過來參考下
    2013-09-09
  • 解析ConcurrentHashMap: 預(yù)熱(內(nèi)部一些小方法分析)

    解析ConcurrentHashMap: 預(yù)熱(內(nèi)部一些小方法分析)

    ConcurrentHashMap是由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成。Segment的結(jié)構(gòu)和HashMap類似,是一種數(shù)組和鏈表結(jié)構(gòu),今天給大家普及java面試常見問題---ConcurrentHashMap知識,一起看看吧
    2021-06-06
  • 全面了解JAVA_BaseDAO數(shù)據(jù)處理類

    全面了解JAVA_BaseDAO數(shù)據(jù)處理類

    下面小編就為大家?guī)硪黄媪私釰AVA_BaseDAO數(shù)據(jù)處理類。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • JAVA中跳出當前多重嵌套循環(huán)的方法詳解

    JAVA中跳出當前多重嵌套循環(huán)的方法詳解

    今天在看面試題時,發(fā)現(xiàn)了這個問題,因為在PHP中跳出多次循環(huán)可以使用break數(shù)字來跳出多層循環(huán),但這在java中并不好使,這篇文章主要給大家介紹了關(guān)于JAVA中跳出當前多重嵌套循環(huán)的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • Java 數(shù)組聲明、創(chuàng)建、初始化詳解

    Java 數(shù)組聲明、創(chuàng)建、初始化詳解

    本文主要介紹Java 數(shù)組聲明、創(chuàng)建、初始化的資料,這里整理相關(guān)知識,及簡單實現(xiàn)代碼,幫助大家學(xué)習(xí),有興趣的小伙伴可以參考下
    2016-09-09
  • mybatis-plus 關(guān)于savebatch,saveorupdatebatch遇到的坑及解決辦法

    mybatis-plus 關(guān)于savebatch,saveorupdatebatch遇到的坑及解決辦法

    本文主要介紹了mybatis-plus 關(guān)于savebatch,saveorupdatebatch遇到的坑及解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Spring Data JPA調(diào)用存儲過程實例代碼

    Spring Data JPA調(diào)用存儲過程實例代碼

    本篇文章主要介紹了Spring Data JPA調(diào)用存儲過程實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-04-04

最新評論