设计模式之Flyweight 通俗理解

设计模式之Flyweight 通俗理解

23种设计模式

Flyweight

n. (拳击或其他比赛中的)特轻量级选手,次最轻量级选手(体重48至51公斤) ;(拳击或其他比赛中的)特轻量级,蝇量级

1 Flyweight 定义

避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类)。

2 为什么使用?

面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大。比如字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗费内存,那么我们还是要"求同存异",找出这些对象群的共同点,设计一个元类,封装可以被共享的类;另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight 中两个重要概念内部状态 intrinsic 和外部状态 extrinsic 之分。

说白点,就是先捏一个的原始模型,然后随着不同场合和环境,再产生各具特征的具体模型,很显然,在这里需要产生不同的新对象,所以 Flyweight 模式中常出现 Factory 模 式.Flyweight 的内部状态是用来共享的,Flyweight factory 负责维护一个Flyweight pool(模式池)来存放内部状态的对象。

Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度.应用场合很多:比如你要从一个数据库中读取一系列字符串,这些字符串中有许多是重复的,那么我们可以将这些字符串储存在Flyweight池(pool)中。

3 如何使用?

比较抽象 ,可以直接看4应用举例

//1我们先从 Flyweight 抽象接口开始:

package xx.study.design.flyweight.case1;

public interface Flyweight {

/**

* 操作

* @param state

*/

public void operation(ExtrinsicState state);

}

//2用于本模式的抽象数据类型(自行设计)

package xx.study.design.flyweight.case1;

/**

* 固有属性 用于本地模式的抽象数据

*/

public interface ExtrinsicState {

}

//3下面是接口的具体实现(ConcreteFlyweight) ,并为内部状态增加内存空间,

//ConcreteFlyweight 必须是可共享的,它保存的任何状态都必须是内部(intrinsic),

//也就是说,ConcreteFlyweight 必须和它的应用环境场合无关.

package xx.study.design.flyweight.case1;

/**

* 具体享元 具体享元类 享原类

* ,ConcreteFlyweight 必须和它的应用环境场合无关.

*/

public class ConcreteFlyweight implements Flyweight{

//内部状态

private IntrinsicState state;

public void operation(ExtrinsicState state) {

//具体操作

}

}

//4当然,并不是所有的 Flyweight 具体实现子类都需要被共享的,所以还有另外一种不

//共享的 ConcreteFlyweight:

package xx.study.design.flyweight.case1;

/**

* 当然,并不是所有的 Flyweight 具体实现子类都需要被共享的,所以还有另外一种不

* 共享的 ConcreteFlyweight:

*/

public class UnsharedConcreteFlyweight implements Flyweight{

public void operation(ExtrinsicState state) {

}

}

//5 Flyweight factory 负责维护一个 Flyweight 池(存放内部状态),当客户端请求

//一个共享 Flyweight 时,这个 factory 首先搜索池中是否已经有可适用的,如果

//有,factory 只是简单返回送出这个对象,否则,创建一个新的对象,加入到池中,再返回送

//出这个对象池

package xx.study.design.flyweight.case1;

import java.util.Hashtable;

/**

*/

public class FlyweightFactory {

//Flyweight pool

private Hashtable flyweights = new Hashtable();

public Flyweight getFlyweight( Object key ) {

Flyweight flyweight = (Flyweight) flyweights.get(key);

if( flyweight == null ) {

//产生新的 ConcreteFlyweight

flyweight = new ConcreteFlyweight();

flyweights.put( key, flyweight );

}

return flyweight;

}

}

//6

//至此,Flyweight 模式的基本框架已经就绪,我们看看如何调用:

//从调用上看,好象是个纯粹的 Factory 使用,但奥妙就在于 Factory 的内部设计上。

package xx.study.design.flyweight.case1;

public class FlyweightDemo {

public static void main(String[] args) {

FlyweightFactory factory = new FlyweightFactory();

Flyweight fly1 = factory.getFlyweight( "Fred" );

Flyweight fly2 = factory.getFlyweight( "Wilma" );

}

}

4 应用举例

网易云上有很多歌曲,缓存所有歌曲时,每个歌曲的歌词不相同,但是歌手可以是相同的,可以抽取出来;实现上述思想。

1原始类

package xx.study.design.flyweight.case2;

/**

* 唱片 相当于Flyweight 元类

*/

public class Song {

private String title;

private int year;

private Artist artist;

public String getTitle() {

return title;

}

public int getYear() {

return year;

}

public Artist getArtist() {

return artist;

}

public void setTitle(String t){

title = t;

}

public void setYear(int y){

year = y;

}

public void setArtist(Artist a){

artist = a;

}

}

2 固有类

package xx.study.design.flyweight.case2;

/**

* 将"歌唱者姓名"作为可共享的 ConcreteFlyweight:

*/

public class Artist {

//内部状态

private String name;

// 歌手是不变的

String getName(){

return name;

}

private int age;

Artist(String n,int age){

this.name = n;

this.age=age;

}

}

3 工厂类 抽取缓存下来

package xx.study.design.flyweight.case2;

import java.util.Hashtable;

public class ArtistFactory {

Hashtable pool = new Hashtable();

public Artist getArtist(String key,int age){

Artist result;

result = (Artist)pool.get(key);

////产生新的 Artist

if(result == null) {

result = new Artist(key,age);

pool.put(key,result);

}

return result;

}

}

4 使用

package xx.study.design.flyweight.case2;

public class cacheSongDemo {

public static void main(String[] args) {

ArtistFactory aFactory=new ArtistFactory();

//歌曲1 2 指向同一对象

Song song1=new Song();

Song song2=new Song();

song1.setArtist( aFactory.getArtist("周杰伦",18));

song2.setArtist( aFactory.getArtist("周杰伦",18));

}

}

相关推荐

AE怎么安装插件?win和mac系统插件、脚本和预设安装教程!
【新闻】“遇见庞贝:永恒之城”展在湖南博物院开幕
365bet手机网址多少

【新闻】“遇见庞贝:永恒之城”展在湖南博物院开幕

📅 08-14 👁️ 4128
[流言板]美加墨世预赛止步18强,中国男足连续6届无缘世界杯决赛圈