什么是flyweight(元享)模式

  对于设计模式我一直都在悟,说实在话,设计模式并不能让你的代码越来越简单,反而会让其复杂化,理解设计模式不难,吸收设计模式是痛苦的过程。 
  设计模式是实践的产物,有需求才有改进,是一种聪明的偷懒方法,gof的设计模式比较抽象化,看看就知道是博士创作出来的东西,高度抽象形成理论,而理论是比较难于理解的,今天我斗胆也来谈谈对设计模式的一点感悟,说实话,现阶段我对设计模式的理解和吸收还在一个比较初级的阶段,所以我开篇说了“悟”,所以有什么说的不对,写的不好的地方还需要各位朋友的支持和改正。 
  废话少说了,今天接触到了flyweight(元享模式),于是我先不急看手边的理论,想先查查资料,看看有什么比较通俗易懂,一针见血的好文,先让我有个直观的感受,回头再结合理论做深入的研究,这是我习惯的学习过程,效果也是不错的,至少印象深刻。但是发现关于此模式的介绍并不多,而且内容差不多,虽然这样,但是看完了一些还是有了认识,学习是要有动力的,现在面临着系统的重构工作,我想这就是我的动力,学以致用,用过了才有资格说自己会了,用的好不好,对不对暂且不说,至少这个过程是有益的,是会促使人思考的,是追求良好设计思想,优秀程序结构的表现。设计模式是要思考的,我往往一个模式要想半天,并不是我想不通,看不懂,而是想它背后的许多,总是有许多为什么,呵呵。 
  什么是flyweight(元享)模式,为什么要叫flyweight? 
  flyweight如果用中文来说是“次最轻量级的拳击选手”的意思,一开始我就很纳闷,为什么取这样一个名字,然后再看看中文对于这种模式的解释,叫“元享”模式,又是一头雾水,虽然说名字只是个称谓,一个记号,但是我相信在给这种模式命名的时候,前辈们应该是考虑过要和这种模式的本质有所关联的,是要符合这种模式本身特点和气质的。看到后来,似乎对英文名和中文名有了那么点感觉,又或者说如果不叫这个名字还能叫什么。 
  什么是flyweight(元享)模式呢?其实就是一种为了避免在我们的系统中产生大量重复对象的方法,也是一种追求解耦,实现封装抵抗需求变化的过程。 
  因为名字之所以有轻量级这层含义,我个人理解是针对系统中这样的对象而言,它们容易被重复产生,因为它们自身比较单纯,本身的侵入性比较小,有一层“轻”的概念在里面,而中文名叫“元享”,分两层来理解,第一,元是什么?我把元认为就是这样的对象,我们为什么会重复创建这些对象,因为它们是本元,万物不离其本元,我给你元,至于你怎么变化,怎么给它添砖加瓦,怎么组合排列那是你的事情,我只负责给你我的这个元,打个比方,我们每个人都有多重角色,你是男人,也是父亲,还是儿子,又是丈夫,区分这些角色的原则是要看你在什么样的环境下,你和谁在一起,比如我是个歌手,我可以出一张JAZZ专辑,也可以出一张ROCK的,或者RAP的,只要你的实力够档次,所以我们会有各式各样的对象就出来,无非是你这个人加上点什么就成了什么,这里就会产生一个问题,如果你把我new在了办公室里我就成了工作时的我,把我new在家里,我就是家里的我了,如果你同时把我new在办公室和家里,就会有两个我,虽然这好像说不通,但是我们本身是不能分身的,在程序里我们完全有能力做到这点,这样不断的new下去会有大量的我出现在各个地方,发挥各种作用,这样多爽啊,呵呵! 
  假如我能分身,那我不希望和这些特有的环境和物质相绑定来完成我的角色,为什么,因为联系的太过紧密,那是什么意思,其实就是高耦合。我需要一个地方来派发单纯的我,然后把我派到各个地方担任各个角色,(这不是工厂模式吗?)没错,元享模式就是应用了工厂模式,我就待在这个工厂里哪也不去,除非有命令,那我就出去。这里需要注意的是我的元神依然在工厂里,你忘记了吧,我会分身的,所以你在工厂外面的只是我的分身。 
  继续往下吧,哎,解释个名字解释半天,看来我终究不是博士,抽象能力太差。。。 
  文字的力量不及代码来的明显,让我举个例子,然后来看看代码。 
  什么例子呢,我自己也不想想了,就用歌手出CD专辑这个例子吧!这样一句话落在我们程序员脑子里就很不一样了,你从这句话中体会到了什么?歌手,CD,或许还有歌,专辑名称等等。。。(万物皆对象) 
  很好,看来你想象能力还真是不错呢,CD这个东西我们就来把他抽象一把,看代码: 
  
 

Java代码 
  1. public abstact class CD{  
  2.     private Artist artist;  
  3.      private CDOtherThings  special;  
  4.      public CD(Artist artist,CDOtherThings special){  
  5.         this.artist=artist;  
  6.         this.special = special;  
  7.      }  
  8.      //忽略了get和set方法  
  9.      public void doSomeSpecial(CDOtherThings special);  
  10. }   
  11. public class CDOtherThings {  
  12.     private String cd_name;  
  13.     private ArrayList<String> songsList;  
  14.     public CDOtherThings(String cdName,ArrayList<String> songsList){  
  15.         this.cd_name = cdName;  
  16. this.songsList = songsList;  
  17.     }  
  18.     public String getCd_name() {  
  19. return cd_name;  
  20.     }  
  21.     public void setCd_name(String cd_name) {  
  22. this.cd_name = cd_name;  
  23.     }  
  24.     public ArrayList<String> getSongsList() {  
  25. return songsList;  
  26.     }  
  27.     public void setSongsList(ArrayList<String> songsList) {  
  28. this.songsList = songsList;  
  29.     }  
  30.  }  
  31. //再来个歌手类  
  32. public class Artist {  
  33.     private String name;  
  34.     private String age;  
  35.     private String company;  
  36.     public Artist(String name){  
  37.         this.name=name;  
  38.     }  
  39.     public String getAge() {  
  40.         return age;  
  41.     }  
  42.     public void setAge(String age) {  
  43.         this.age = age;  
  44.     }  
  45.     public String getCompany() {  
  46.         return company;  
  47.     }  
  48.     public void setCompany(String company) {  
  49.         this.company = company;  
  50.     }  
  51.     public String getName() {  
  52.         return name;  
  53.     }  
  54.     public void setName(String name) {  
  55.         this.name = name;  
  56.     }  
  57.   }  

  我刚才说了,歌手是一直要待在工厂里提供给外面的是分身了,那么让我们来搞个工厂吧,注意,这可以此模式的精髓哦! 
 
Java代码 
  1.  public class ArtistFactory {  
  2.   
  3.      private Hashtable<String,Artist> artist_table;  
  4.   
  5.      public Artist getArtist(String name){  
  6.          Artist artist = null;  
  7.  if(artist_table==null){  
  8.      artist_table = new Hashtable<String,Artist>();  
  9.      artist = new Artist(name);  
  10.      artist_table.put(name,artist);  
  11.      return artist;  
  12.           }  
  13.           artist = artist_table.get(name);  
  14.   if(artist==null){  
  15.       artist = new Artist(name);  
  16.       artist_table.put(name,artist);  
  17.    }  
  18.    return artist;  
  19. }  
  20.  }  

  我在这个工厂里维护了一个数据结构,我们的元神就待在这里,命令来了我们要看一下这个数据结构中有没有我们想要的元神,如果有就给他,其实给的是副本了,如果没有我们就创建一个给它,但是我们还要把它放在元神共存的这个数据结构里,这里,这个key就很重要了,我们方便起见就拿歌手名称来作为key去找本人咯,呵呵。 
  接下来让我们继承一下这个CD类吧 
  
 
Java代码 
  1.     
  2. public class CDChild extends CD{      
  3.     public CDChild(Artist artist,CDOtherThings special){  
  4.         super(artist,special);      
  5.     }  
  6.     public void doSomeSpecial(CDOtherThings special){  
  7.         String cd_name = special.getCd_name();  
  8.         ArrayList<String> songsList = special.getSongsList();  
  9.         if(cd_name==null||"".equals(cd_name)){  
  10.             System.out.println("no cd name!");  
  11.        return;  
  12.     }  
  13.     if(songsList==null||songsList.size()==0){  
  14.         System.out.println(cd_name+"no songs!");  
  15.         return;  
  16.     }  
  17.     int size = songsList.size();  
  18.     for(int i=0;i<size;i++){  
  19.         String songName = songsList.get(i);  
  20.         System.out.println(songName);  
  21.     }  
  22.      }  
  23.   }  
  24.   //下面就是测试代码咯  
  25.   public class Test {  
  26.       
  27.       public static void main(String[]args){  
  28.           
  29.           ArrayList<String> songsList = new ArrayList<String>();  
  30.      songsList.add("aSong");  
  31.      songsList.add("bSong");  
  32.      CDOtherThings special = new CDOtherThings("CD_NAME_ONE",songsList);  
  33.      ArtistFactory factory = new ArtistFactory();  
  34.      Artist artist = factory.getArtist("LP");  
  35.      CD cd = new CDChild(artist,special);  
  36.         cd.doSomeSpecial(special);  
  37.      }  
  38.     }    
  39.     

  此时,“LP”这个乐队在这里就出了这样一张“CD_NAME_ONE”这张专辑,但是不管我用这种方式给“LP”去发几张不同的专辑,“LP”在工厂里有一个元神。这就避免了重复创建“LP”。 
  flyweight(享元)模式还有两个概念: 
  1,intrinsic 内部状态 
  2,extrinsic 外部状态 
  其实就是Artist和CDOtherThings的意思,我是这么理解的。 
  当然,此模式也可以不支持共享元神对象的,这里就不多做说明了,这里的不共享是指Artist对象,我可以待在那个数据结构中等待命令来调用我,也可以每次都new一下new一下,具体情况具体分析了。 
  写完了,也不知道例子卡不恰当,表述的清楚不清楚,希望能对一些朋友有帮助,同时也是对自己学习的一个总结,相当于再一次学习和升华。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值