博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
享元模式
阅读量:3953 次
发布时间:2019-05-24

本文共 5010 字,大约阅读时间需要 16 分钟。

享元模式(Flyweight)

运用共享技术有效地支持大量细粒度的对象。

让不同的客户透明地使用面向对象的方法操作。

例子:网站

class WebSite{	private String name="";	public WebSite(String name)	{		this.name=name;	}	public void Use()	{		System.out.println("网站分类:"+name);	}}public class main{	public static void main(String[] args) {		WebSite fx=new WebSite("产品展示");fx.Use();		WebSite fy=new WebSite("产品展示");fy.Use();		WebSite fz=new WebSite("产品展示");fz.Use();		WebSite fl=new WebSite("博客");fl.Use();		WebSite fm=new WebSite("博客");fm.Use();		WebSite fn=new WebSite("博客");fn.Use();	}}

如果要做三个产品展示,三个博客的网站就需要六个网站类的实例,但是本质上都是一样的代码,如果网站增多,实例也就增多,这对服务器资源浪费严重。

解决方法:具体数据和模板可以不同,但核心代码和数据库可以共享。

享元对象能做到共享的关键是区分内部状态和外部状态。

如:文本编辑器中通常将每一个字母做成一个享元对象。
享元的内部状态就是这个字母,字母在文本中的位置和子模风格等其他信息则是外部状态
虽然这些字母的位置和字模风格不同,但是所有这些地方使用的都是同一个字母对象。这样,字母对象就可以在整个系统中共享。
 

abstract class Flyweight//Flyweight类,它是所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态{	public String intrinsic;//内部状态	protected final String extrinsic;//外部状态	//要求享元角色必须接受外部状态	public Flyweight(String extrinsic)	{		this.extrinsic=extrinsic;	}	public abstract void operate(int extrinsic);//定义业务操作	public String getIntrinsic() {		return intrinsic;	}	public void setIntrinsic(String intrinsic) {		this.intrinsic = intrinsic;	}	}class ConcreteFlyweight extends Flyweight//继承并为内部状态增加存储空间{	public ConcreteFlyweight(String extrinsic)	{//接受外部状态		super(extrinsic);	}   //根据外部状态进行逻辑处理	@Override	public void operate(int extrinsic) {		// TODO Auto-generated method stub		System.out.println("具体Flyweight:"+extrinsic);	}}class UnsharedConcreteFlyweight extends Flyweight//指不需要共享的Flyweight子类,不强制共享。{	public UnsharedConcreteFlyweight(String extrinsic)	{		super(extrinsic);	}	public void operate(int extrinsic) {		// TODO Auto-generated method stub		System.out.println("不共享的具体Flyweight:"+extrinsic);	}}class FlyweightFactory//享元工厂,用来创建并管理Flyweight对象,当用户请求一个Flyweight是,工厂对象提供一个已创建的实例或者创建一个。{	private static HashMap
pool=new HashMap
(); public static Flyweight getFlyweight(String extrinsic) { Flyweight flyweight=null; if(pool.containsKey(extrinsic)) {//池中有该对象 flyweight =pool.get(extrinsic); System.out.print("已有"+extrinsic+"直接从池中取--->"); }else {//根据外部状态创建享元对象 flyweight =new ConcreteFlyweight(extrinsic); pool.put(extrinsic, flyweight);//放入池中 System.out.print("创建"+extrinsic+"并从池中取出--->"); } return flyweight; } }public class main{ public static void main(String[] args) { int extrinsic=22; FlyweightFactory f=new FlyweightFactory(); Flyweight flyweightX=f.getFlyweight("X"); flyweightX.operate(--extrinsic); Flyweight flyweightY=f.getFlyweight("Y"); flyweightY.operate(--extrinsic); Flyweight flyweightZ=f.getFlyweight("Z"); flyweightZ.operate(--extrinsic); Flyweight flyweightRex =f.getFlyweight("X"); flyweightRex.operate(--extrinsic); Flyweight unsharedFlyweight = new UnsharedConcreteFlyweight("X"); unsharedFlyweight.operate(--extrinsic);}}

结果:

创建X并从池中取出--->具体Flyweight:21

创建Y并从池中取出--->具体Flyweight:20
创建Z并从池中取出--->具体Flyweight:19
已有X直接从池中取--->具体Flyweight:18
不共享的具体Flyweight:17
 

 FlyweightFactory根据客户需求返回生成好的对象,但实际上不一定需要事先生成对象的实例,完全可以初始化时什么也不做,到需要时,再去判断对象是否已经存在来决定是否实例化。

UnsharedConcreteFlyweight用来解决不需要共享对象的问题,为什么?

因为尽管大部分时间我们都需要共享对象来降低内存的损耗,但个别时候也有可能不需要共享的,那么此时的UnsharedConcreteFlyweight就有存在的必要了,用它去解决那些不惜要共享对象的问题。

内部状态与外部状态

共享网站代码:

class User{//外部状态,用户类	private String name;	User(String name)	{		this.name=name;	}	public String getName()	{		return name;	}	public void setName(String name)	{		this.name=name;	}}abstract class WebSite{	public abstract  void Use(User user);	}class ConcreteWebSite extends WebSite{	private String name="";	public ConcreteWebSite(String name)	{		this.name=name;	}	public void Use(User user)	{		System.out.println("网站分类:"+name+"用户:"+user.getName());	}}class WebSiteFactory{	//定义一个池容器	private static HashMap
flyweights=new HashMap
(); //获得网站分类 public WebSite GetWebSiteCategory(String key) { if(!flyweights.containsKey(key)) { WebSite flyweight=new ConcreteWebSite(key); flyweights.put(key, flyweight); } return (flyweights.get(key)); } public int GetWebSiteCount()//获得网站分类总数 { return flyweights.size(); }}public class main{ public static void main(String[] args) { WebSiteFactory f=new WebSiteFactory(); WebSite fx=f.GetWebSiteCategory("产品展示");fx.Use(new User("小菜")); WebSite fy=f.GetWebSiteCategory("产品展示");fy.Use(new User("大鸟")); WebSite fz=f.GetWebSiteCategory("产品展示");fz.Use(new User("娇娇")); WebSite fl=f.GetWebSiteCategory("博客");fl.Use(new User("老顽童")); WebSite fm=f.GetWebSiteCategory("博客");fm.Use(new User("桃谷六仙")); WebSite fn=f.GetWebSiteCategory("博客");fn.Use(new User("南海神鳄")); System.out.println("网站分类总数为"+f.GetWebSiteCount());}}

结果:

网站分类:产品展示用户:小菜

网站分类:产品展示用户:大鸟
网站分类:产品展示用户:娇娇
网站分类:博客用户:老顽童
网站分类:博客用户:桃谷六仙
网站分类:博客用户:南海神鳄
网站分类总数为2
 

 享元模式设计的重点就在于分离变与不变

把一个对象的状态分成内部状态和外部状态,内部状态是不变的,外部状态是可变的。

然后通过共享不变的部分,达到减少对象数量节约内存。

享元模式应用场合:

  1. 一个系统有大量的对象
  2. 这些对象耗费大量的内存
  3. 这些对象的状态中的大部分都可以外部化
  4. 这些对象可以按照内部状态分成很多的组,当把外部对象从对象中删除时,每一组都可以仅用一个对象代替。

 享元模式优点:

降低内存中对象的数量,节省内存空间。
缺点:
使得系统更加的复杂。将享元对象外部化,使运行时间变长,逻辑变得相当复杂。

因此,只有当有足够多的对象实例可供共享时才值得使用享元模式!

转载地址:http://xxyzi.baihongyu.com/

你可能感兴趣的文章
大数据技术之Hadoop(入门)第1章 大数据概论
查看>>
大数据技术之Hadoop(入门) 第2章 从Hadoop框架讨论大数据生态
查看>>
大数据技术之Hadoop(入门)第3章 Hadoop运行环境搭建
查看>>
大数据技术之Hadoop(入门)第4章 Hadoop运行模式
查看>>
大数据技术之Hadoop(入门)第5章 Hadoop编译源码
查看>>
大数据技术之Hadoop(入门)第6章 常见错误及解决方案
查看>>
大数据技术之Hadoop(HDFS)第1章 HDFS概述
查看>>
大数据技术之Hadoop(HDFS)第2章 HFDS的Shell操作
查看>>
大数据技术之HBase第3章 HBase数据结构
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>
Java 之23种设计模式解析
查看>>