设计模式--享元模式FlyWeight(结构型)_flyweight模式类图-程序员宅基地

技术标签: 设计模式  

1 定义:

1.1 定义:Use sharing to support large numbers of fine-grained objects efficiently.(使用共享对象可以有效地支持大量的细粒度的对象。)

细粒度对象:不可避免地使得对象数量多且性质相近,可将这些对象的信息分为两个部分:内部状态(intrinsic)与外部状态(extrinsic)。

内部状态:对象可共享出来的信息,存储在享元对象的内部并且不会随环境改变而改变

外部状态:对象得以依赖的一个标记:随环境改变而改变、不可以共享的状态,享元对象的外蕴状态必须由由端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部

(理解举例:享元模式在编辑器系统中大量使用。一个文编辑器往往会提供很多种字体,而通常的做法就是将每一个字母做成一个享元对象。享元对象的内蕴状态就是这个字母,而字母在文本中的位置和字体风格等其他信息则是外蕴状态。比如,字母a可以出现在文本的很多地方,虽然这些字母a的位置和字体风格不同,但是所有这些地方使用的都是同一个字母对象。这样一来,字母对象就可以在整个系统中共享。

1.2 通用类图:

Flyweight——抽象享元角色

一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。

ConcreteFlyweight——具体享元角色

实现抽象角色定义的业务。该角色中需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是不允许的。

UnsharedConcreteFlyweight——不可共享的享元角色

不存在外部状态或者安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。

FlyweightFactory——享元工厂

职责非常简单,就是构造一个池容器,同时提供从池中获得对象的方式。

1.3 通用代码:

错误举例:

 

package _22_Flyweight;
public abstract class Flyweight {
	private String intrinsic;
	protected String extrinsic;

	public Flyweight(String intrinsic) {
		this.intrinsic = intrinsic;
	}

	public String getIntrinsic() {
		return intrinsic;
	}

	public abstract void operate();

	public String getExtrinsic() {
		return extrinsic;
	}

	public void setExtrinisic(String extrinsic) {
		this.extrinsic = extrinsic;
	}
}

public class ConcreteFlyweight1 extends Flyweight {
	public ConcreteFlyweight1(String intrinsic) {
		super(intrinsic);
	}

	public void operate() {
	}
}

public class ConcreteFlyweight2 extends Flyweight {
	public ConcreteFlyweight2(String intrinsic) {
		super(intrinsic);
	}

	public void operate() {
	}
}

public class FlyweightFactory {
	private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>();

	public static Flyweight getFlyweight1(String Intrinsic) {
		// 需要返回的对象
		Flyweight flyweight = pool.get(Intrinsic);
		if (flyweight == null) {
			flyweight = new ConcreteFlyweight1(Intrinsic);
			pool.put(Intrinsic, flyweight);
		}
		return flyweight;
	}

	public static int getSize() {
		return pool.size();
	}
}

public class Client {
	public static void main(String args[]) {
		Flyweight fly1 = FlyweightFactory.getFlyweight1("1234567890");
		fly1.setExtrinisic("Pos: line=10, col=20, color = RED");
		System.out.println(fly1.getExtrinsic() + " " + fly1.getIntrinsic());
		Flyweight fly2 = FlyweightFactory.getFlyweight1("1234567890");
		fly2.setExtrinisic("Pos: line=20, col=20, color = BLUE");
		System.out.println(fly2.getExtrinsic() + " " + fly2.getIntrinsic());
		System.out.println("池中数量为:" + FlyweightFactory.getSize());
	}
}

结果:

Pos: line=10, col=20, color = RED 1234567890

Pos: line=20, col=20, color = BLUE 1234567890

池中数量为:1

注意上述是一个误用(错例)。

享元模式只是想将对象细粒度化,将可共享部分缓存起来,以复用。而上例中将对象的共享部分与非共享部分融合在一起是错误的,因为这样则会导致整体的复用,在一个对象未被消费时,其会被另一次复用覆盖。而这并非复用的本质。

下例正确:

 
package _22_Flyweight.right;
public abstract class Flyweight {
	private String intrinsic;

	public Flyweight(String intrinsic) {
		this.intrinsic = intrinsic;
	}

	public String getIntrinsic() {
		return intrinsic;
	}

	public abstract void operate();
}

public class ConcreteFlyweightContent extends Flyweight {
	public ConcreteFlyweightContent(String intrinsic) {
		super(intrinsic);
	}

	public void operate() {
	}
}

public class FlyweightFactory {
	private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>();

	public static Flyweight getFlyweight1(String Intrinsic) {
		// 需要返回的对象
		Flyweight flyweight = pool.get(Intrinsic);
		if (flyweight == null) {
			flyweight = new ConcreteFlyweightContent(Intrinsic);
			pool.put(Intrinsic, flyweight);
		}
		return flyweight;
	}

	public static int getSize() {
		return pool.size();
	}
}

public class WPS {
	Flyweight fly;
	List<String> formats = new ArrayList<String>();
	List<Flyweight> contents = new ArrayList<Flyweight>();

	public void addLine(String format, Flyweight content) {
		formats.add(format);
		contents.add(content);
	}

	public void show() {
		for (int i = 0; i < formats.size(); i++) {
			System.out.print(formats.get(i) + "\t\t");
			System.out.println(contents.get(i).getIntrinsic());
		}
	}
}

public class Client {
	public static void main(String args[]) {
		WPS mydoc = new WPS();
		mydoc.addLine("Pos: line=1, col=20, color = RED",
				FlyweightFactory.getFlyweight1("1234567890"));
		mydoc.addLine("Pos: line=2, col=20, color = GREEN",
				FlyweightFactory.getFlyweight1("1234567890"));
		mydoc.addLine("Pos: line=3, col=20, color = BLUE",
				FlyweightFactory.getFlyweight1("1234567890"));
		mydoc.show();
		System.out.println("池中数量为:" + FlyweightFactory.getSize());
	}
}

2 优点

2.1 大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能;

3 缺点

3.1 提高了系统的复杂性:需要分离出外部状态和内部状态;

4 应用场景

4.1 系统存在大量的相似对象;

4.2 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份;

4.3 需要缓冲池的场景。

5 注意事项

暂无

6 扩展

暂无

7 范例

暂无

转自: http://blog.csdn.net/yuanlong_zheng/article/details/7584881
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/benbenxiongyuan/article/details/23782305

智能推荐

将cram/bam文件转换为fastq文件_cram转成bam-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏5次。NCBI下载的cram文件无法直接使用,需要先转成bam/sam文件,根据官网说明下载了cramtools,发现早已没有维护,报错如下:$ java -jar cramtools-3.0.jarError: Invalid or corrupt jarfile cramtools-3.0.jar所以就直接用samtools来转换,但是直接转换会报错:$ samtools view -b NA12878.final.cram > NA12878.bam &Failed to popu_cram转成bam

INS/GNSS组合导航(三)松耦合、紧耦合、深度耦合_gnss/ins-程序员宅基地

文章浏览阅读1.4w次,点赞33次,收藏222次。INS/GNSS组合导航,松耦合、紧耦合、深度耦合异同对比_gnss/ins

poj 2676 Sudoku_数独 17997-程序员宅基地

文章浏览阅读288次。SudokuTime Limit: 2000MS Memory Limit: 65536KTotal Submissions: 17997 Accepted: 8714 Special JudgeDescriptionSudoku is a very simple task. A square table with_数独 17997

【渝粤教育】电大中专计算机职业素养 (9)作业 题库_a 职业习惯 b 职业道德 c 职业意识 d 职业化-程序员宅基地

文章浏览阅读486次。1.( )就是合适的时间、合适的地点、做合适的事A.职业习惯B.职业意识C.职业化D.职业道德错误正确答案:左边查询学生答案:未作答2.曾经的一项调查发现一些企业业绩不好,客户流失的最重要的原因是( )。A.企业员工素养达不到要求B.企业管理问题C.企业产品价格不好D.企业产品质量问题错误正确答案:左边查询学生答案:未作答3.用冰山模型说明职业素养构成时,我们把浮在水面上面的知识、技能等部分称为( )的职业素养。A.显性B.专业C.获得D.隐性错_a 职业习惯 b 职业道德 c 职业意识 d 职业化

质性数据分析软件NVivo的编码比较查询_nvivo kappa系数-程序员宅基地

文章浏览阅读7.9k次。NVivo是一款支持定性研究方法和混合研究方法的软件。它的编码比较查询是比较两个用户完成的编码,以衡量“评估者之间的可靠性”或用户之间编码的同意程度。它使您能够比较由两个用户或两组用户完成的编码。通过计算百分比一致性和“ Kappa系数”,这是提供了测量“评估者间可靠性”或用户之间一致性程度的方法。协议百分比是协议单位数除以数据项内的总度量单位,以百分比显示。 Kappa系数是一种统计量度,其中考虑了可能通过偶然性达成的协议量。创建编码比较查询在“浏览”选项卡上的“查询”组中,单击“ 编码比较”_nvivo kappa系数

angular双向绑定无效果,ng-model不能正常显示_angularjs ng-model 数据不显示-程序员宅基地

文章浏览阅读5.8k次。今天遇到了个问题,js代码中变量已经变化了,但是html页面中没有正常的显示出来。代码如下:&lt;input type="text" ng-model="paramValue" auto-focus&gt;$scope.paramValue = param;以上代码就会造成有时input框中无内容的情况,打断点显示$scope.paramValue是有值的,但是页面就是啥都显示不出来。换成下边代..._angularjs ng-model 数据不显示

随便推点

HttpPost_httppost hp = new httppost-程序员宅基地

文章浏览阅读382次。public class MainActivity extends AppCompatActivity { private TextView tvShow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSt_httppost hp = new httppost

C++ 之头文件声明定义_c++跨平台头文件声明-程序员宅基地

文章浏览阅读2.5k次,点赞5次,收藏21次。最近在学习 c++, 在编译与链接过程中遇到了一些定义与声明的问题, 经过多处查阅资料, 基本解惑. 现记录与此, 希望让后面人少走些弯路.C++ 的头文件应该用什么扩展名?目前业界的常用格式如下:implementation file*.cpp*.cc*.cc*.cheader file*.hpp*.h++*.hh*.hxx*.h一句话: 建议 源文件使用 .cpp, 头文件使用 .hpp关于 implementation file 并没有什么说的, 使用._c++跨平台头文件声明

Android 集成Tinker踩坑记录_android tinker-程序员宅基地

文章浏览阅读9.4k次。高版本AGP集成Tinker踩坑记录,加固包补丁如何生成,TInker补丁的管理规范。_android tinker

Sum It Up POJ 1564 HDU 杭电1258【DFS】_problem description given a specified total t and -程序员宅基地

文章浏览阅读942次。Problem DescriptionGiven a specified total t and a list of n integers, find all distinct sums using numbers from the list that add up to t. For example, if t=4, n=6, and the list is [4,3,2,2,1,1],_problem description given a specified total t and a list of n integers, find

使用springboot集成mybatis出现错误:CLIENT_PLUGIN_AUTH is required_mybatis client_plugin_auth is required-程序员宅基地

文章浏览阅读227次。问题:java.sql.SQLNonTransientConnectionException: CLIENT_PLUGIN_AUTH is required at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) ~[mysql-connector-java-8.0.23.jar:8.0.23] at com.mysql.cj.jdbc.exceptions.SQLError.crea..._mybatis client_plugin_auth is required

在DeepinOS下运行《最终幻想14》网游_deepin ff14-程序员宅基地

文章浏览阅读2.1k次。篇Log用于记录如何在Deepin 15.11下运行Final Fantasy XIV。(WeGame版本没有测试)结论:通过测试,这个游戏可以在Linux下和Android下完整的玩(硬件配置必须OK)。问题分析: 运行网游,需要知道的是有几个要点: 1.需要安装DirectX 2.需要中文支持 3.需要能打开登录界面。 踩的坑: FF14的首次..._deepin ff14