11.java設計模式之享元模式
阿新 • • 發佈:2020-11-19
#### 基本需求:
* 小型的外包專案,給客戶A做一個產品展示網站,客戶A的朋友感覺效果不錯,也希望做這樣的產品展示網站,但是要求都有些不同
* 每個客戶要求釋出的方式不一樣,A要求以新聞的方式釋出,B要求以部落格的方式釋出,C要求以公眾號的方式釋出,並且多個釋出人可能選擇用同一種方式釋出
#### 傳統方案:
* 直接複製A客戶的網站,在其上按照B的要求修改,定製化,給每個網站都租用一個空間
* 需要的網站結構相似度很高,而且都不是高訪問量網站,如果分成多個虛擬空間來處理,相當於一個相同網站的例項物件很多,造成伺服器的資源浪費
* 解決思路:整合到一個網站中,共享其相關的程式碼和資料,對於硬碟、記憶體、CPU、資料庫空間等伺服器資源都可以達成共享,減少伺服器資源
#### 基本介紹:
* 享元模式(Flyweight)也叫'蠅量模式',主要用於減少建立物件的數量,以減少記憶體佔用和提高效能。這種型別的設計模式屬於結構型模式,它提供了減少物件數量從而改善應用所需的物件結構的方式。享元模式嘗試重用現有的同類物件,如果未找到匹配的物件,則建立新物件,有匹配的物件,則直接使用
* 運用共享技術有效地支援大量細粒度的物件,主要解決:在有大量物件時,有可能會造成記憶體溢位,我們把其中共同的部分抽象出來,如果有相同的業務請求,直接返回在記憶體中已有的物件,避免重新建立
* 常用於系統底層開發,解決系統的效能問題。像資料庫連線池,裡面都是建立好的連線物件,在這些連線物件中有我們需要的則直接拿來用,避免重新建立,如果沒有我們需要的,則建立一個
* 享元模式能夠解決重複物件的記憶體浪費的問題,當系統中有大量相似物件,需要緩衝池時。不需總是建立新物件,可以從緩衝池裡拿。這樣可以降低系統記憶體,同時提高效率
* 享元模式經典的應用場景就是池技術了,String 常量池、資料庫連線池、緩衝池等等都是享元模式的應用,享元模式是池技術的重要實現方式
* UML類圖(原理)
* ![](https://img2020.cnblogs.com/blog/2093590/202011/2093590-20201119192540671-128836225.png)
* 說明
* FlyWeight 是抽象的享元角色, 他是產品的抽象類, 同時定義出物件的外部狀態和內部狀態的介面或實現
* 享元模式提出了兩個要求:細粒度和共享物件。這裡就涉及到內部狀態和外部狀態了,即將物件的資訊分為兩個部分:內部狀態和外部狀態
* 內部狀態指物件共享出來的資訊, 儲存在享元物件內部且不會隨環境的改變而改變
* 外部狀態指物件得以依賴的一個標記,是 隨環境改變而改變的、不可共享的狀態
* 例如:下五子棋,圍棋等,使用的棋子就可以用享元模式定義,棋子的顏色就是內部狀態(兩種顏色不會改變),棋子在棋盤的位置隨選手的落子而決定就是外部狀態;
* 可在棋子類 建立兩個屬性 一個顏色,一個位置,落子時每次在工廠獲取的都是同一個物件,只不過位置屬性的值不同而已,達到了這兩個棋子物件的複用
* ConcreteFlyWeight 是具體的享元角色,是具體的產品類,實現抽象角色定義相關業務
* UnSharedConcreteFlyWeight 是不可共享的角色,一般不會出現在享元工廠(一般也不會出現)
* FlyWeightFactory 享元工廠類,內部構建一個池容器(集合),同時提供從池中獲取物件方法
* UML類圖(案例)
* ![](https://img2020.cnblogs.com/blog/2093590/202011/2093590-20201119192550645-128055333.png)
* 說明
* WebSite有不同的釋出狀態,用type表示,也就是其內部狀態,ConcreteWebSite為其實現類,具體的享元角色
* User為外部狀態,不同的User可以用相同的方式去釋出WebSite
* WebSiteFactory為工廠類,用於維護WebSite池
* 程式碼實現
* >```java
>public abstract class WebSite {
>
> // 享元抽象類
>
> // 此屬性為內部狀態,釋出的形式只有幾種,新聞,部落格,公眾號
> protected String type;
>
> public WebSite(String type) {
> this.type = type;
> }
>
> // 使用User類作為外部狀態,不同的User可以釋出同一形式的網站(實際使用的是同一WebSite物件)達到了物件的複用
> public abstract void use(User user);
>
>}
>
>// 具體的享元類
>class ConcreteWebSite extends WebSite{
>
> // 具體的享元產品
>
> public ConcreteWebSite(String type) {
> super(type);
> }
>
> @Override
> public void use(User user) {
> System.out.println(user.getName() + "用" + this.type + "形式釋出了網站");
> }
>
>}
>```
>
>
* >```java
>@Data
>@AllArgsConstructor
>public class User {
>
> // WebSite的外部狀態
> private String name;
>
>}
>```
>
>
* >```java
>public class WebSiteFactory {
>
> // 享元工廠類,內部維護享元產品池
>
> pri