享元模式

享元模式(Flyweigh)

动机:避免大量细粒度对象问题的同时,让外部客户程序扔能够透明地使用面向对象的方式操作。
实例:不同网站具体数据和模板不同,核心代码和数据库共享

 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<String,Flyweight> pool=new HashMap<String,Flyweight>();
	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用来解决不需要共享对象的问题。

关于含有外部状态的共享网站代码

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<String,WebSite> flyweights=new HashMap<String,WebSite>();
	//获得网站分类
	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

享元模式设计的重点就在***分离变与不变***。把一个对象的状态分成内部状态和外部状态,内部状态是不变的,外部状态是可变的。然后通过共享不变的部分,达到减少对象数量节约内存。

享元模式使用情况:

  • 一个系统有大量的对象
  • 这些对象耗费大量的内存
  • 这些对象的状态中的大部分都可以外部化
  • 这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一组都可以仅用一个对象代替。
    优点:
    降低内存中对象的数量,节省内存空间
    缺点:
    使得系统更加的复杂。将享元对象外部化,使运行时间变长。

本质

分离和共享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值