也谈设计模式(Flyweight)

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

[code]
public abstact class CD{
private Artist artist;
private CDOtherThings special;
public CD(Artist artist,CDOtherThings special){
this.artist=artist;
this.special = special;
}
//忽略了get和set方法
public void doSomeSpecial(CDOtherThings special);
}
public class CDOtherThings {
private String cd_name;
private ArrayList<String> songsList;
public CDOtherThings(String cdName,ArrayList<String> songsList){
this.cd_name = cdName;
this.songsList = songsList;
}
public String getCd_name() {
return cd_name;
}
public void setCd_name(String cd_name) {
this.cd_name = cd_name;
}
public ArrayList<String> getSongsList() {
return songsList;
}
public void setSongsList(ArrayList<String> songsList) {
this.songsList = songsList;
}
}
//再来个歌手类
public class Artist {
private String name;
private String age;
private String company;
public Artist(String name){
this.name=name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
[/code]
我刚才说了,歌手是一直要待在工厂里提供给外面的是分身了,那么让我们来搞个工厂吧,注意,这可以此模式的精髓哦!
[code]
public class ArtistFactory {

private Hashtable<String,Artist> artist_table;

public Artist getArtist(String name){
Artist artist = null;
if(artist_table==null){
artist_table = new Hashtable<String,Artist>();
artist = new Artist(name);
artist_table.put(name,artist);
return artist;
}
artist = artist_table.get(name);
if(artist==null){
artist = new Artist(name);
artist_table.put(name,artist);
}
return artist;
}
}
[/code]
我在这个工厂里维护了一个数据结构,我们的元神就待在这里,命令来了我们要看一下这个数据结构中有没有我们想要的元神,如果有就给他,其实给的是副本了,如果没有我们就创建一个给它,但是我们还要把它放在元神共存的这个数据结构里,这里,这个key就很重要了,我们方便起见就拿歌手名称来作为key去找本人咯,呵呵。
接下来让我们继承一下这个CD类吧

[code]

public class CDChild extends CD{
public CDChild(Artist artist,CDOtherThings special){
super(artist,special);
}
public void doSomeSpecial(CDOtherThings special){
String cd_name = special.getCd_name();
ArrayList<String> songsList = special.getSongsList();
if(cd_name==null||"".equals(cd_name)){
System.out.println("no cd name!");
return;
}
if(songsList==null||songsList.size()==0){
System.out.println(cd_name+"no songs!");
return;
}
int size = songsList.size();
for(int i=0;i<size;i++){
String songName = songsList.get(i);
System.out.println(songName);
}
}
}
//下面就是测试代码咯
public class Test {

public static void main(String[]args){

ArrayList<String> songsList = new ArrayList<String>();
songsList.add("aSong");
songsList.add("bSong");
CDOtherThings special = new CDOtherThings("CD_NAME_ONE",songsList);
ArtistFactory factory = new ArtistFactory();
Artist artist = factory.getArtist("LP");
CD cd = new CDChild(artist,special);
cd.doSomeSpecial(special);
}
}
[/code]
此时,“LP”这个乐队在这里就出了这样一张“CD_NAME_ONE”这张专辑,但是不管我用这种方式给“LP”去发几张不同的专辑,“LP”在工厂里有一个元神。这就避免了重复创建“LP”。
flyweight(享元)模式还有两个概念:
1,intrinsic 内部状态
2,extrinsic 外部状态
其实就是Artist和CDOtherThings的意思,我是这么理解的。
当然,此模式也可以不支持共享元神对象的,这里就不多做说明了,这里的不共享是指Artist对象,我可以待在那个数据结构中等待命令来调用我,也可以每次都new一下new一下,具体情况具体分析了。
写完了,也不知道例子卡不恰当,表述的清楚不清楚,希望能对一些朋友有帮助,同时也是对自己学习的一个总结,相当于再一次学习和升华。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值