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

23種設計模式(21)java享元模式

 更新時間:2018年01月27日 10:34:05   作者:java_my_life  
這篇文章主要為大家詳細介紹了23種設計模式之java享元模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下

在閻宏博士的《JAVA與模式》一書中開頭是這樣描述享元(Flyweight)模式的:

Flyweight在拳擊比賽中指最輕量級,即“蠅量級”或“雨量級”,這里選擇使用“享元模式”的意譯,是因為這樣更能反映模式的用意。享元模式是對象的結構模式。享元模式以共享的方式高效地支持大量的細粒度對象。

Java中的String類型

  在JAVA語言中,String類型就是使用了享元模式。String對象是final類型,對象一旦創(chuàng)建就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會確保一個字符串常量在常量池中只有一個拷貝。String a="abc",其中"abc"就是一個字符串常量。

public class Test {
 public static void main(String[] args) {
  String a = "abc";
  String b = "abc";
  System.out.println(a==b);
 }
}

上面的例子中結果為:true ,這就說明a和b兩個引用都指向了常量池中的同一個字符串常量"abc"。這樣的設計避免了在創(chuàng)建N多相同對象時所產生的不必要的大量的資源消耗。

享元模式的結構

  享元模式采用一個共享來避免大量擁有相同內容對象的開銷。這種開銷最常見、最直觀的就是內存的損耗。享元對象能做到共享的關鍵是區(qū)分內蘊狀態(tài)(Internal State)外蘊狀態(tài)(External State) 。

       一個內蘊狀態(tài)是存儲在享元對象內部的,并且是不會隨環(huán)境的改變而有所不同。因此,一個享元可以具有內蘊狀態(tài)并可以共享。

    一個外蘊狀態(tài)是隨環(huán)境的改變而改變的、不可以共享的。享元對象的外蘊狀態(tài)必須由客戶端保存,并在享元對象被創(chuàng)建之后,在需要使用的時候再傳入到享元對象內部。外蘊狀態(tài)不可以影響享元對象的內蘊狀態(tài),它們是相互獨立的。

  享元模式可以分成單純享元模式和復合享元模式兩種形式。

單純享元模式  

  在單純的享元模式中,所有的享元對象都是可以共享的。

單純享元模式所涉及到的角色如下:

抽象享元(Flyweight)角色:給出一個抽象接口,以規(guī)定出所有具體享元角色需要實現(xiàn)的方法。
具體享元(ConcreteFlyweight)角色:實現(xiàn)抽象享元角色所規(guī)定出的接口。如果有內蘊狀態(tài)的話,必須負責為內蘊狀態(tài)提供存儲空間。
享元工廠(FlyweightFactory)角色:本角色負責創(chuàng)建和管理享元角色。本角色必須保證享元對象可以被系統(tǒng)適當?shù)毓蚕?。當一個客戶端對象調用一個享元對象的時候,享元工廠角色會檢查系統(tǒng)中是否已經有一個符合要求的享元對象。如果已經有了,享元工廠角色就應當提供這個已有的享元對象;如果系統(tǒng)中沒有一個適當?shù)南碓獙ο蟮脑?,享元工廠角色就應當創(chuàng)建一個合適的享元對象。

源代碼

抽象享元角色類

public interface Flyweight {
 //一個示意性方法,參數(shù)state是外蘊狀態(tài)
 public void operation(String state);
}

具體享元角色類ConcreteFlyweight有一個內蘊狀態(tài),在本例中一個Character類型的intrinsicState屬性代表,它的值應當在享元對象被創(chuàng)建時賦予。所有的內蘊狀態(tài)在對象創(chuàng)建之后,就不會再改變了。

如果一個享元對象有外蘊狀態(tài)的話,所有的外部狀態(tài)都必須存儲在客戶端,在使用享元對象時,再由客戶端傳入享元對象。這里只有一個外蘊狀態(tài),operation()方法的參數(shù)state就是由外部傳入的外蘊狀態(tài)。

public class ConcreteFlyweight implements Flyweight {
 private Character intrinsicState = null;
 /**
 * 構造函數(shù),內蘊狀態(tài)作為參數(shù)傳入
 * @param state
 */
 public ConcreteFlyweight(Character state){
  this.intrinsicState = state;
 }
 
 /**
 * 外蘊狀態(tài)作為參數(shù)傳入方法中,改變方法的行為,
 * 但是并不改變對象的內蘊狀態(tài)。
 */
 @Override
 public void operation(String state) {
  // TODO Auto-generated method stub
  System.out.println("Intrinsic State = " + this.intrinsicState);
  System.out.println("Extrinsic State = " + state);
 }
}

享元工廠角色類,必須指出的是,客戶端不可以直接將具體享元類實例化,而必須通過一個工廠對象,利用一個factory()方法得到享元對象。一般而言,享元工廠對象在整個系統(tǒng)中只有一個,因此也可以使用單例模式。

當客戶端需要單純享元對象的時候,需要調用享元工廠的factory()方法,并傳入所需的單純享元對象的內蘊狀態(tài),由工廠方法產生所需要的享元對象。

public class FlyweightFactory {
 private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();
 
 public Flyweight factory(Character state){
  //先從緩存中查找對象
  Flyweight fly = files.get(state);
  if(fly == null){
   //如果對象不存在則創(chuàng)建一個新的Flyweight對象
   fly = new ConcreteFlyweight(state);
   //把這個新的Flyweight對象添加到緩存中
   files.put(state, fly);
  }
  return fly;
 }
}

客戶端類

public class Client {

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  FlyweightFactory factory = new FlyweightFactory();
  Flyweight fly = factory.factory(new Character('a'));
  fly.operation("First Call");
  
  fly = factory.factory(new Character('b'));
  fly.operation("Second Call");
  
  fly = factory.factory(new Character('a'));
  fly.operation("Third Call");
 }
}

雖然客戶端申請了三個享元對象,但是實際創(chuàng)建的享元對象只有兩個,這就是共享的含義。運行結果如下:


復合享元模式

  在單純享元模式中,所有的享元對象都是單純享元對象,也就是說都是可以直接共享的。還有一種較為復雜的情況,將一些單純享元使用合成模式加以復合,形成復合享元對象。這樣的復合享元對象本身不能共享,但是它們可以分解成單純享元對象,而后者則可以共享。


復合享元角色所涉及到的角色如下:

抽象享元(Flyweight)角色:給出一個抽象接口,以規(guī)定出所有具體享元角色需要實現(xiàn)的方法。

具體享元(ConcreteFlyweight)角色:實現(xiàn)抽象享元角色所規(guī)定出的接口。如果有內蘊狀態(tài)的話,必須負責為內蘊狀態(tài)提供存儲空間。

復合享元(ConcreteCompositeFlyweight)角色:復合享元角色所代表的對象是不可以共享的,但是一個復合享元對象可以分解成為多個本身是單純享元對象的組合。復合享元角色又稱作不可共享的享元對象。

享元工廠(FlyweightFactory)角色:本角 色負責創(chuàng)建和管理享元角色。本角色必須保證享元對象可以被系統(tǒng)適當?shù)毓蚕?。當一個客戶端對象調用一個享元對象的時候,享元工廠角色會檢查系統(tǒng)中是否已經有 一個符合要求的享元對象。如果已經有了,享元工廠角色就應當提供這個已有的享元對象;如果系統(tǒng)中沒有一個適當?shù)南碓獙ο蟮脑?,享元工廠角色就應當創(chuàng)建一個 合適的享元對象。

源代碼

抽象享元角色類

public interface Flyweight {
 //一個示意性方法,參數(shù)state是外蘊狀態(tài)
 public void operation(String state);
}

具體享元角色類

public class ConcreteFlyweight implements Flyweight {
 private Character intrinsicState = null;
 /**
 * 構造函數(shù),內蘊狀態(tài)作為參數(shù)傳入
 * @param state
 */
 public ConcreteFlyweight(Character state){
  this.intrinsicState = state;
 }
 
 /**
 * 外蘊狀態(tài)作為參數(shù)傳入方法中,改變方法的行為,
 * 但是并不改變對象的內蘊狀態(tài)。
 */
 @Override
 public void operation(String state) {
  // TODO Auto-generated method stub
  System.out.println("Intrinsic State = " + this.intrinsicState);
  System.out.println("Extrinsic State = " + state);
 }

}

復合享元對象是由單純享元對象通過復合而成的,因此它提供了add()這樣的聚集管理方法。由于一個復合享元對象具有不同的聚集元素,這些聚集元素在復合享元對象被創(chuàng)建之后加入,這本身就意味著復合享元對象的狀態(tài)是會改變的,因此復合享元對象是不能共享的。

復合享元角色實現(xiàn)了抽象享元角色所規(guī)定的接口,也就是operation()方法,這個方法有一個參數(shù),代表復合享元對象的外蘊狀態(tài)。一個復合享元對象的所有單純享元對象元素的外蘊狀態(tài)都是與復合享元對象的外蘊狀態(tài)相等的;而一個復合享元對象所含有的單純享元對象的內蘊狀態(tài)一般是不相等的,不然就沒有使用價值了。

public class ConcreteCompositeFlyweight implements Flyweight {
 
 private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();
 /**
 * 增加一個新的單純享元對象到聚集中
 */
 public void add(Character key , Flyweight fly){
  files.put(key,fly);
 }
 /**
 * 外蘊狀態(tài)作為參數(shù)傳入到方法中
 */
 @Override
 public void operation(String state) {
  Flyweight fly = null;
  for(Object o : files.keySet()){
   fly = files.get(o);
   fly.operation(state);
  } 
 }
}

享元工廠角色提供兩種不同的方法,一種用于提供單純享元對象,另一種用于提供復合享元對象。

public class FlyweightFactory {
 private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();
 /**
 * 復合享元工廠方法
 */
 public Flyweight factory(List<Character> compositeState){
  ConcreteCompositeFlyweight compositeFly = new ConcreteCompositeFlyweight();
  
  for(Character state : compositeState){
   compositeFly.add(state,this.factory(state));
  }
  
  return compositeFly;
 }
 /**
 * 單純享元工廠方法
 */
 public Flyweight factory(Character state){
  //先從緩存中查找對象
  Flyweight fly = files.get(state);
  if(fly == null){
   //如果對象不存在則創(chuàng)建一個新的Flyweight對象
   fly = new ConcreteFlyweight(state);
   //把這個新的Flyweight對象添加到緩存中
   files.put(state, fly);
  }
  return fly;
 }
}

客戶端角色

public class Client {

 public static void main(String[] args) {
  List<Character> compositeState = new ArrayList<Character>();
  compositeState.add('a');
  compositeState.add('b');
  compositeState.add('c');
  compositeState.add('a');
  compositeState.add('b');
  
  FlyweightFactory flyFactory = new FlyweightFactory();
  Flyweight compositeFly1 = flyFactory.factory(compositeState);
  Flyweight compositeFly2 = flyFactory.factory(compositeState);
  compositeFly1.operation("Composite Call");
  
  System.out.println("---------------------------------");  
  System.out.println("復合享元模式是否可以共享對象:" + (compositeFly1 == compositeFly2));
  
  Character state = 'a';
  Flyweight fly1 = flyFactory.factory(state);
  Flyweight fly2 = flyFactory.factory(state);
  System.out.println("單純享元模式是否可以共享對象:" + (fly1 == fly2));
 }
}

運行結果如下:

從運行結果可以看出,一個復合享元對象的所有單純享元對象元素的外蘊狀態(tài)都是與復合享元對象的外蘊狀態(tài)相等的。即外運狀態(tài)都等于Composite Call。
從運行結果可以看出,一個復合享元對象所含有的單純享元對象的內蘊狀態(tài)一般是不相等的。即內蘊狀態(tài)分別為b、c、a。
從運行結果可以看出,復合享元對象是不能共享的。即使用相同的對象compositeState通過工廠分別兩次創(chuàng)建出的對象不是同一個對象。
從運行結果可以看出,單純享元對象是可以共享的。即使用相同的對象state通過工廠分別兩次創(chuàng)建出的對象是同一個對象。

享元模式的優(yōu)缺點

        享元模式的優(yōu)點在于它大幅度地降低內存中對象的數(shù)量。但是,它做到這一點所付出的代價也是很高的:

享元模式使得系統(tǒng)更加復雜。為了使對象可以共享,需要將一些狀態(tài)外部化,這使得程序的邏輯復雜化。
享元模式將享元對象的狀態(tài)外部化,而讀取外部狀態(tài)使得運行時間稍微變長。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Spring @Component自定義注解實現(xiàn)詳解

    Spring @Component自定義注解實現(xiàn)詳解

    @Component是一個元注解,意思是可以注解其他類注解,如@Controller @Service @Repository @Aspect。官方的原話是:帶此注解的類看為組件,當使用基于注解的配置和類路徑掃描的時候,這些類就會被實例化
    2022-09-09
  • spring?batch線上異常定位記錄

    spring?batch線上異常定位記錄

    這篇文章主要為大家介紹了spring?batch線上異常定位記錄及異常解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-03-03
  • 基于Java并發(fā)容器ConcurrentHashMap#put方法解析

    基于Java并發(fā)容器ConcurrentHashMap#put方法解析

    下面小編就為大家?guī)硪黄贘ava并發(fā)容器ConcurrentHashMap#put方法解析。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java 虛擬機棧詳解分析

    Java 虛擬機棧詳解分析

    在線程創(chuàng)建時,JVM會為每個線程創(chuàng)建一個單獨的棧空間。JVM的棧內存不需要是連續(xù)的。JVM在棧上會進行兩個操作:壓入和彈出棧幀。對于一個特定的線程來說,棧被稱為運行時棧。這個線程調用的每個方法會被存儲在響應的運行時棧里,包括了參數(shù),局部變量,計算媒介和其他數(shù)據(jù)
    2021-11-11
  • Java中八種基本數(shù)據(jù)類型的默認值

    Java中八種基本數(shù)據(jù)類型的默認值

    這篇文章主要介紹了Java中八種基本數(shù)據(jù)類型的默認值 的相關資料,需要的朋友可以參考下
    2016-07-07
  • @Scheduled注解不能同時執(zhí)行多個定時任務的解決方案

    @Scheduled注解不能同時執(zhí)行多個定時任務的解決方案

    這篇文章主要介紹了@Scheduled注解不能同時執(zhí)行多個定時任務的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • SpringBoot解決406錯誤之返回對象缺少Getter/Setter方法引發(fā)的問題

    SpringBoot解決406錯誤之返回對象缺少Getter/Setter方法引發(fā)的問題

    在Spring Boot開發(fā)中,接口請求返回數(shù)據(jù)是系統(tǒng)交互的重要環(huán)節(jié),然而,開發(fā)過程中常常會遇到由于數(shù)據(jù)類型或返回格式問題導致的錯誤,其中最常見的就是406 Not Acceptable異常,本篇文章以實際的案例出發(fā),詳細分析在POST請求中產生406錯誤的原因
    2024-11-11
  • Java中的 BigDecimal 和 String 的相互轉換問題

    Java中的 BigDecimal 和 String 的相互轉換問題

    這篇文章主要介紹了Java中的 BigDecimal 和 String 的相互轉換問題,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • 使用Idea快速搭建SpringMVC項目的詳細步驟記錄

    使用Idea快速搭建SpringMVC項目的詳細步驟記錄

    這篇文章主要給大家介紹了關于使用Idea快速搭建SpringMVC項目的詳細步驟,Spring?MVC是一種基于MVC模式的框架,它是Spring框架的一部分,它提供了一種更簡單和更有效的方式來構建Web應用程序,需要的朋友可以參考下
    2024-05-05
  • Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳解

    Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳

    本文主要介紹了Thread.currentThread().getName()?和?this.getName()區(qū)別詳解,TestThread?testThread?=?new?TestThread();
    2022-02-02

最新評論

玉田县| 板桥市| 班戈县| 商洛市| 剑河县| 社会| 乐东| 繁昌县| 孟州市| 阜新市| 灵宝市| 涿州市| 寿光市| 麻江县| 闵行区| 夏河县| 鄂州市| 曲沃县| 肇东市| 类乌齐县| 泸州市| 山阳县| 西乡县| 汽车| 平谷区| 静海县| 江阴市| 平陆县| 寿宁县| 台安县| 黑山县| 宁河县| 六枝特区| 娱乐| 丰宁| 余干县| 章丘市| 江源县| 子洲县| 博白县| 色达县|