享元模式 - 結構型模式

模式類型:

??? Flyweight?? 享元模式 - 結構型模式?

意圖:
????
The intent of this pattern is to use sharing to support a large number of objects that have part of their internal state in common where the other part of state can vary.
??? 運用共享技術有效地支持大量細粒度的對象.
?? ?
概述:
?? ?
享元模式的作用在于節省內存開銷,對于系統內存在的大量相似的對象,通過享元的設計方式,可以提取出可共享的部分,將其只保留一份進而節省大量的內存開銷。

?? ?并不是所有的對象都適合進行享元設計,它要求對象具有可共享的特征,這些可共享的特征可以做享元設計,對象的可共享特征比例越大,進行享元設計后節省的內存越多。
?? ?注意,對象的不可共享特征不能計入享元設計,所以需要仔細判斷區分對象的可共享特征與不可共享特征。


????享元模式的本質是:分離和共享。分離的是對象狀態中變與不變的部分,共享的是對象中不變的部分。享元模式的關鍵之處就是在于分離變與不變,把不變的部分作為享元對象的內部狀態,把變化的部分作為外部狀態,這樣享元對象就可以達到共享的目的,從而減少對象數量,節約內存空間。
?? ?
角色:
??? 1、抽象享元(Flyweight)角色:享元接口,通過這個接口可以接收并作用于外部狀態。通過這個接口傳入外部的狀態,在享元對象的方法處理中可能會使用這些外部狀態數據。
??? 2、具體享元(ConcreteFlyweight)角色:具體的享元對象,必須是共享的,需要封裝Flyweight的內部狀態。
??? 3、非共享的具體享元(UnsharedConcreteFlyweight)角色:非共享的具體享元對象,并不是所有的Flyweight對象都需要共享,非共享的享元對象通常是對共享享元對象的組合對象。
??? 4、享元工廠(FlyweightFactory)角色:享元工廠,主要用來創建并管理共享的享元對象,并對外提供訪問共享享元對象的接口。
??? 5、客戶端(Client)角色:享元客戶端,主要的工作是維持一個對享元對象的引用,計算或存儲享元對象的外部狀態,也可以訪問共享和非共享的享元對象。

模式的應用場景:
?? ?1 一個應用程序使用了大量的對象
?? ?2 完全由于使用大量的對象,造成很大的存儲開銷?
?? ?3 對象的大多數狀態都可變為外部狀態
?? ?4 如果刪除對象的外部狀態,那么可以用相對較少的共享對象取代很多組對象
?? ?5 應用程序不依賴對象標識.由于Flyweight對象可以被共享,對于概念明顯有別的想對象,標識測試將返回真值.

結構圖:

?

模式的優缺點:


代碼:
網上的實例都差不多,這里還有一個外國網站的(和下面的實例差不多):http://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm

import java.util.HashMap;  import java.util.Map;  class ServiceContext {  private int tableIndex;  private String customerName;  public ServiceContext(int tableIndex, String customerName) {  this.tableIndex = tableIndex;  this.customerName = customerName;  }  public int getTableIndex() {  return tableIndex;  }  public String getCustomerName() {  return customerName;  }  }  interface Drink {  void provideService(ServiceContext serviceContext);  }  class Coffee implements Drink {  public Coffee() {  System.out.println("Coffee is created.");  }  @Override  public void provideService(ServiceContext serviceContext) {  System.out.println("Coffee is serving for table " + serviceContext.getTableIndex() + " customer " + serviceContext.getCustomerName());  }  }  class Tea implements Drink {  public Tea() {  System.out.println("Drink is created.");  }  @Override  public void provideService(ServiceContext serviceContext) {  System.out.println("Drink is serving for table " + serviceContext.getTableIndex() + " customer " + serviceContext.getCustomerName());  }  }  class Water implements Drink {  public Water() {  System.out.println("Water is created.");  }  @Override  public void provideService(ServiceContext serviceContext) {  System.out.println("Water is serving for table " + serviceContext.getTableIndex() + " customer " + serviceContext.getCustomerName());  }  }  class DrinkFactory {  private Map<String, Drink> drinks = new HashMap<>();  public Drink createDrink(String type) {  Drink drink = drinks.get(type);  if (drink == null) {  // 以下可以考慮抽象工廠模式實現以符合開閉原則,也可以使用反射  if (type.equals("Water")) {  drink = new Water();  } else if (type.equals("Tea")) {  drink = new Tea();  } else if (type.equals("Coffee")) {  drink = new Coffee();  }  drinks.put(type, drink);  }  return drink;  }  }  public class WaiterTest {  public static void main(String[] args) {  String[] types = {"Water", "Tea", "Coffee"};  DrinkFactory drinkFactory = new DrinkFactory();  for (int i = 1; i <= 9; i++) {  Drink drink = drinkFactory.createDrink(types[i % 3]);// Drink 可共享特征 在 DrinkFactory 內部實現享元  ServiceContext serviceContext = new ServiceContext(i, "Sir" + i);// 服務細節為不可共享特征,不能享元  drink.provideService(serviceContext);//外部特征,不可共享特征,保證調用過程不會影響下次調用。  
            }  }  }  

輸出:

Drink is created.  
Drink is serving for table 1 customer Sir1  
Coffee is created.  
Coffee is serving for table 2 customer Sir2  
Water is created.  
Water is serving for table 3 customer Sir3  
Drink is serving for table 4 customer Sir4  
Coffee is serving for table 5 customer Sir5  
Water is serving for table 6 customer Sir6  
Drink is serving for table 7 customer Sir7  
Coffee is serving for table 8 customer Sir8  
Water is serving for table 9 customer Sir9

可以看出:在9次的服務過程中,飲品只創建了三次,一種飲品都僅僅創建了一次,減小了很多內存開銷,服務可以很好的進行。
這就是享元模式的精髓,但務必注意區分出可共享與不可共享部分,保證不可共享部分在使用之后不會影響下次使用,即不會改變可共享部分。

相關模式:
??? 享元模式與單例模式:兩者可以組合使用。享元模式中的享元工廠完全可以實現為單例,另外,享元工廠中緩存的享元對象,都是單例實例,可以看成是單例模式的一種變形控制,在享元工廠中來單例享元對象。
??? 享元模式與組合模式:兩者可以組合使用。在享元模式中,存在不需要共享軟件的享元實現,這些不需要共享的享元通常是對共享的享元對象的組合對象。換句話來說,就是通過將將兩種模式組合使用,可以實現更復雜的對象層次結構。
??? 享元模式與狀態模式:兩者可以組合使用。可以使用享元模式來共享狀態模式中的狀態對象。通常在狀態模式中,會存在數量很大的,細粒度的狀態對象,而且它們基本上可以重復使用的,都是用來處理某一個固定的狀態的,它們需要的數據通常都是由上下文傳入,也就是變化部分都被分離出去呢,所以可以用享元模式來實現這些狀態對象呢。
??? 享元模式與策略模式:兩者可以組合使用。也可以使用享元來實現策略模式中的策略對象。和狀態模式一樣,策略模式中也存在大量細粒度的策略對象,它們需要的數據同樣也是從上下文傳入的,因而可以通過享元模式來實現這些策略對象。

?

所有模式:
?? ? 創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
??? 行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
??? 補充模式:空對象模式

?

原文地址:https://blog.csdn.net/paincupid/article/details/46896653

?

轉載于:https://www.cnblogs.com/tartis/p/9288750.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251303.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251303.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251303.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端試題(四)

1. vue過濾器使用場景 2. v-on綁定多個方法 <p v-on"{click:dbClick,mousemove:MouseClick}"></p>一個事件綁定多個函數&#xff1a; <p click"one(),two()">點擊</p>3. 在菜單結構不確定時&#xff0c;前端如何動態渲染 樹形…

http --- 用于HTTP調試的最小型Perl Web 服務器

下面的程序是個很有用戶的診斷工具,可以用來調試與客戶端和代理的交互情況. 該程序 首先會等待HTTP連接,只有收到請求報文,就會將報文打印在屏幕上,然后等待用戶輸入一條響應報文,并將其回送給客戶端. #! /usr/bin/perl use Socket; use Carp; use FileHandle;# (1) use prot …

Mysql - 安裝與配置

1、下載安裝包 > https://www.mysql.com/downloads/ 2、雙擊安裝&#xff0c;點擊Install MySQL Products > 3、Skip 打鉤&#xff0c;Next下一步 > 4、選擇Server only&#xff1a;只選擇安裝服務端&#xff0c;根據個人喜好更改安裝路徑和數據保存路徑…

4084:拓撲排序

題目鏈接&#xff1a;http://bailian.openjudge.cn/practice/4084/ 總時間限制: 1000ms 內存限制: 65536kB描述給出一個圖的結構&#xff0c;輸出其拓撲排序序列&#xff0c;要求在同等條件下&#xff0c;編號小的頂點在前。 輸入若干行整數&#xff0c;第一行有2個數&#xff…

廖雪峰git教程學習

廖雪峰git教程 git – Linus在2周內用c寫的 1.1 基本概念 版本控制系統&#xff0c;追蹤文本文件的改動&#xff0c;文件、視頻等二進制文件則不可追蹤&#xff08;微軟的word也是二進制文件&#xff09;HEAD 指向當前分支&#xff0c;表示當前版本&#xff08;最新的提交&am…

操作系統 --- 進程和管程的不同

1.進程定義的是私有數據結構PCB,管程定義的是公共數據結構,如消息隊列等; 2.進程是由順序程序執行有關操作,而管程主要是進行同步操作和初始化操作; 3.設置進程的目的在于實現系統的并發行,而管程的設置則是解決共享資源的互斥使用問題; 4.進程通過調用管程中的過程對共享數據結…

JCO 自定義DestinationDataProvider

要讓JAVA程序能訪問SAP系統&#xff0c;一般通過SAP JCO接口進行通訊&#xff0c;在獲取到SAP的連接時需求提供一些連接參數&#xff0c;這些參數在最新的 JCO 3.0 中需要被保存到一個帶有擴展名.jcoDestination的文件中&#xff0c;這個文件同時被保存在應用程序的安裝目錄中。…

android BLE Peripheral 手機模擬設備發出BLE廣播 BluetoothLeAdvertiser

android 從4.3系統開始可以連接BLE設備&#xff0c;這個大家都知道了。iOS是從7.0版本開始支持BLE。android 進入5.0時代時&#xff0c;開放了一個新功能&#xff0c;手機可以模擬設備發出BLE廣播&#xff0c; 這個新功能其實是 對標于 iOS系統的手機模擬iBeacon設備。先介紹一…

前端后臺管理系統梳理

再梳理一遍 一、商品后臺管理系統 1. 功能 1.1 服務端情況 開啟了CORS跨域支持需要授權的 API &#xff0c;必須在請求頭中使用 Authorization 字段提供token 令牌&#xff08;axios攔截器&#xff09;baseUrl&#xff0c;接口地址&#xff1a;http://localhost:8888/api/…

操作系統 --- 使用套接字進行網絡通信

一個套接字就是一個通信標識類型的數據結構,包含了通信目的的地址、通信使用的端口號、通信網絡的傳輸協議、進程所在的網絡地址,以及針對客戶或服務器程序提供的不同系統調用等,是進程通信和網絡通信的基本構件。套接字是為客戶/服務器模型而設計的,通常分為以下兩類: 1.基于…

構造器執行順序

轉載于:https://www.cnblogs.com/a6948076/p/8045801.html

Java08-java語法基礎(七)構造方法

Java08-java語法基礎&#xff08;七&#xff09;構造方法 一、構造方法 1、什么是構造方法&#xff1f; 構造方法&#xff08;類方法&#xff09;是一個方法名和類名相容的特殊的成員方法。 2、構造方法的作用&#xff1f; 當使用new關鍵字創建一個對象時&#xff0c;為新建對象…

安裝mysql8.0.20,報錯“找不到VCRUNTIME140_1.dll”

寫在最前&#xff0c;指令集合 以管理員身份運行cmd mysql -uroot -p 【進入】mysql mysql > exit 【退出】 net stop mysql 【暫停】 net start mysql 【啟動】 mysql -u root -p&#xff08;命令后輸入臨時密碼&#xff0c;進入mysql&#xff09; ALTER USER USER() …

操作系統 --- 線程與進程的比較

如果說,在操作系統中引入進程的目的是為了使多個程序能并發執行,以提高資源利用率和系統吞吐量,那么在操作系統中再引入線程,則是為了減少程序在并發執行時所付出的時空開銷,使OS(操作系統)具有更好的并發性… 我們再回顧一下進程的兩個基本屬性: 1.進程是一個可擁擁有資源的獨…

24種吸引人的營銷文章標題寫法,總有一個適合你!

在如今信息爆炸的互聯網時代下&#xff0c;如何提高提高文章的閱讀(新聞稿、軟文宣傳稿、微信公眾號)&#xff0c;成為從業者們共同研究的課題?首先你得有一個足夠吸引的標題&#xff0c;尤其是定向推送的時候&#xff0c;這將是由一個質變帶來量變的過程。小編雖然不提倡標題…

[js] 處理字符串換行造成的json解析失敗

需求&#xff1a;從數據庫某個字段取出字符串出來&#xff0c;轉為json&#xff0c;結果發現報錯為 解析失敗&#xff0c;發現是因為取出的字符串換行導致&#xff0c;現在需要將字符串里面的換行替換為&#xff0c;使字符串可依成功解析成json對象。 技術&#xff1a;依靠repl…

使用mockjs模擬數據

一、安裝 簡單粗暴 npm install mockjs 二、引入 CommonJS引入 let Mock require(mockjs) let userInfo Mock.mock({data: {responseCode: 200,responseMessage: success,userMessage: {name: "cname",email: "email",msg: cparagraph(2)}} })或者ES…

angular --- ngDialog關閉當前層

今天做項目,使用ngDialog 彈出了一層,并且在彈出層上又彈出了第二層. 現在想點擊確定按鈕關閉第二層. 使用以前的ngDialog.close()會關閉掉全部ngDialog.open方法彈出來的層. 在網上查了一堆,找了好多,最后發現就一句話.$scope.closeThisDialog(); 注意, 要在controller:中傳遞…

lodash源碼分析之compact中的遍歷

小時候&#xff0c; 鄉愁是一枚小小的郵票&#xff0c; 我在這頭&#xff0c; 母親在那頭。 長大后&#xff0c;鄉愁是一張窄窄的船票&#xff0c; 我在這頭&#xff0c; 新娘在那頭。 后來啊&#xff0c; 鄉愁是一方矮矮的墳墓&#xff0c; 我在外頭&#xff0c; 母親在里頭。…

[HAOI2008]移動玩具

這又是一道神奇的搜索題。。。只要記錄每種狀態。。。然后暴力判斷這種狀態往后一步的情況。。。 廣搜出最優解即可。。。 呆碼&#xff1a; #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std;int dx[5]{0…