目錄
什么是享元模式
享元模式的實現(xiàn)
享元模式角色
享元模式類圖
享元模式代碼實現(xiàn)
享元模式的特點
優(yōu)點
缺點
使用場景
注意事項
什么是享元模式
????????享元模式(Flyweight Pattern)是一種結(jié)構(gòu)型設(shè)計模式,享元模式中的“享元”指被共享的單元,享元模式通過復(fù)用對象,以達到節(jié)省內(nèi)存的目的。要求能夠共享的對象必須是細(xì)粒度對象,因此它又稱為輕量級模式。其主要解決的問題是創(chuàng)建大量相似對象時的內(nèi)存開銷過大。
????????其意圖運用共享技術(shù)有效地支持大量細(xì)粒度的對象。解決在有大量對象時,有可能會造成內(nèi)存溢出問題,把其中共同的部分抽象出來,查找時直接返回在內(nèi)存中已有的對象,沒有才重新創(chuàng)建,避免重新創(chuàng)建已有對象。減少創(chuàng)建對象的數(shù)量,以減少內(nèi)存占用和提高性能,避免大量相似對象的開銷,從而提高系統(tǒng)資源的利用率,盡可能復(fù)用現(xiàn)有的同類對象。
????????“享元”,被共享的單元,即復(fù)用對象,節(jié)省內(nèi)存,注意前提是享元對象是不可變對象。
????????當(dāng)一個系統(tǒng)中存在大量重復(fù)不可變對象,就能利用享元模式將對象設(shè)計成享元,在內(nèi)存中只保留一份實例,供引用。這就減少內(nèi)存中對象的數(shù)量,最終節(jié)省內(nèi)存。當(dāng)然,不僅相同對象可設(shè)計成享元,相似對象,也能提取對象中的相同部分(字段)設(shè)計成享元。
????????“不可變對象”:一旦通過構(gòu)造器初始化完成后,其狀態(tài)(對象的成員變量或?qū)傩裕┚筒粫俦恍薷摹K?,不可變對象不能暴露任何set()等修改內(nèi)部狀態(tài)的方法。之所以要求享元是不可變對象,是因為它會被多處代碼共享使用,避免一處代碼對享元進行了修改,影響到其他使用它的代碼。
享元模式的實現(xiàn)
享元(Flyweight )模式中存在以下兩種狀態(tài):
1.?內(nèi)部狀態(tài),即不會隨著環(huán)境的改變而改變的可共享部分。
2.?外部狀態(tài),指隨環(huán)境改變而改變的不可以共享的部分。享元模式的實現(xiàn)要領(lǐng)就是區(qū)分應(yīng)用中的這兩種狀態(tài),并將外部狀態(tài)外部化。
享元模式角色
- 抽象享元角色(Flyweight):通常是一個接口或抽象類,在抽象享元類中聲明了具體享元類公 共的方法,這些方法可以向外界提供享元對象的內(nèi)部數(shù)據(jù)(內(nèi)部狀態(tài)),同時也可以通過這些方法來設(shè)置外部數(shù)據(jù)(外部狀態(tài))。
- 具體享元角色(Concrete Flyweight):實現(xiàn)了抽象享元類,稱為享元對象;在具體享元 類中為內(nèi)部狀態(tài)提供了存儲空間。通常我們可以結(jié)合單例模式來設(shè)計具體享元類,為每一個具體享元類提供唯一的享元對象。
- 非享元角色(Unsharable Flyweight) :并非所有的抽象享元類的子類都需要被共享,不 能被共享的子類可設(shè)計為非共享具體享元類;當(dāng)需要一個非共享具體享元類的對象時可以直接通過實例化創(chuàng)建。
- 享元工廠角色(Flyweight Factory):負(fù)責(zé)創(chuàng)建和管理享元角色。當(dāng)客戶對象請求一個享元 對象時,享元工廠檢査系統(tǒng)中是否存在符合要求的享元對象,存在則提供給客戶,不存在新創(chuàng)建提供給客戶。
享元模式類圖
享元模式代碼實現(xiàn)
抽象享元角色
package com.common.demo.pattern.flyweight;
/**
* @author Evan Walker 昂焱數(shù)據(jù): https://www.ayshuju.com
* @version 1.0
* @desc 抽象享元角色 籃球
* @date 2023/07/21 15:03:57
*/
public interface BasketBall {
void play();
}
具體享元角色和非享元角色
package com.common.demo.pattern.flyweight;
/**
* @author Evan Walker 昂焱數(shù)據(jù): https://www.ayshuju.com
* @version 1.0
* @desc 具體享元角色 體育館
* @date 2023/07/21 15:05:37
*/
public class Gymnasium implements BasketBall{
private String gymnasiumName;
private String sport = "籃球";
double price = 50;
public Gymnasium() {
}
public Gymnasium(String gymnasiumName) {
this.gymnasiumName = gymnasiumName;
}
public String getGymnasiumName() {
return gymnasiumName;
}
public void setGymnasiumName(String gymnasiumName) {
this.gymnasiumName = gymnasiumName;
}
public String getSport() {
return sport;
}
public void setSport(String sport) {
this.sport = sport;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public void play() {
System.out.println("Gymnasium{" + "gymnasiumName='" + gymnasiumName + '\'' +
", sport='" + sport + '\'' + ", price=" + price + '}'
+", this Object='" + this + '\'' );
}
}
享元工廠角色
package com.common.demo.pattern.flyweight;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* @author Evan Walker 昂焱數(shù)據(jù): https://www.ayshuju.com
* @version 1.0
* @desc 享元工廠 籃球工廠
* @date 2023/07/21 15:11:37
*/
public class BasketBallFactory {
private static Map<String,Gymnasium> MAP = new HashMap<>();
public static Gymnasium getBasketBall(String gymnasiumName){
Gymnasium gymnasium = MAP.get(gymnasiumName);
if(Objects.isNull(gymnasium)){
gymnasium = new Gymnasium(gymnasiumName);
MAP.put(gymnasiumName,gymnasium);
}
return gymnasium;
}
}
測試類
package com.common.demo.pattern.flyweight;
import java.util.ArrayList;
import java.util.List;
/**
* @author Evan Walker 昂焱數(shù)據(jù): https://www.ayshuju.com
* @version 1.0
* @desc
* @date 2023/07/21 15:16:00
*/
public class Test {
private static final List<String> nameList = new ArrayList<>();
public static void main(String[] args) {
nameList.add("斯塔普斯中心球館");
nameList.add("大通中心球館");
nameList.add("麥迪遜花園球館");
nameList.add("聯(lián)合中心球館");
nameList.add("速貸中心球館");
nameList.add("斯塔普斯中心球館");
nameList.add("速貸中心球館");
nameList.add("美航球館");
nameList.add("丹佛百事中心球館");
for (String name : nameList){
BasketBallFactory.getBasketBall(name).play();
}
}
}
測試截圖
文章來源:http://www.zghlxwxcb.cn/news/detail-602384.html
享元模式的特點
優(yōu)點
- 大大減少對象的創(chuàng)建,對象復(fù)用,降低系統(tǒng)的內(nèi)存,使效率提高。
缺點
- 提高了系統(tǒng)的復(fù)雜度,需要分離出外部狀態(tài)和內(nèi)部狀態(tài),而且外部狀態(tài)具有固有化的性質(zhì),不應(yīng)該隨著內(nèi)部狀態(tài)的變化而變化,否則會造成線程安全問題。
- 需要犧牲一定的時間和空間,來實現(xiàn)對象共享和控制機制。當(dāng)對象之間沒有復(fù)用性時,使用享元模式可能會導(dǎo)致額外的開銷。
使用場景
- 系統(tǒng)有大量相似對象。
- 當(dāng)對象需要被共享時,如需要緩沖池的場景。
- 當(dāng)系統(tǒng)的內(nèi)存資源相對有限時可以考慮使用享元模式,以減少內(nèi)存的使用。
- 當(dāng)需要減少對象的創(chuàng)建次數(shù)、降低系統(tǒng)開銷時。
注意事項
- 注意劃分外部狀態(tài)和內(nèi)部狀態(tài),否則可能會引起線程安全問題。
- 這些類必須有一個工廠對象加以控制。
更多消息資訊,請訪問昂焱數(shù)據(jù)(https://www.ayshuju.com)文章來源地址http://www.zghlxwxcb.cn/news/detail-602384.html
到了這里,關(guān)于設(shè)計模式結(jié)構(gòu)型——享元模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!