设计模式(Java)----享元模式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();
		}
}

结果:
网站分类:产品展示
网站分类:产品展示
网站分类:产品展示
网站分类:博客
网站分类:博客
网站分类:博客

存在问题:如果网站增多,实例也增多,这对服务器的资源浪费得很严重。
解决方案:大网站里的各个小网站具体数据和模板可以不同,但核心代码和数据库却是共享的。
享元模式:运用共享技术有效地支持大量细粒度的对象。
享元对象能做到共享的关键是区分内部状态(InternalState)和外部状态(External State)。
内部状态:存储在享元对象内部并且不会随环境改变而改变。因此内部状态可以共享。
外部状态:随环境改变而改变的、不可以共享的状态。享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。
外部状态与内部状态是相互独立的。

 

 

1、ConcreteFlyweight继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。
2、UnsharedConcrefeFlweght是指那些不需要共享的FlyWeight子类,因为FlyWeight接口,使共享成为可能,但它不强制共享,它解决了那些不需要共享对象的问题。

3、FlyweightFactory是一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时, FlyweightFactory对象提供一个已创建的实例或者创建一个新的实例。
 

import java.util.HashMap;

abstract class Flyweight{//所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。
	public String intrinsic;//内部状态
	protected final String extrinsic;//外部状态
	//要求享元角色必须接受外部状态
	public Flyweight(String extrinsic) {
		this.extrinsic=extrinsic;
	}
	public abstract void operate(int extrinsic);//定义业务操作
	public String getIntrisic() {
		return intrinsic;
	}
	public void setIntrinsic(String intrinsic) {
		this.intrinsic=intrinsic;
	}
}
//ConcreteFlyweight继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。
class ConcreteFlyweight extends Flyweight{
	//接受外部状态
	public ConcreteFlyweight(String extrinsic) {
		super(extrinsic);
		// TODO Auto-generated constructor stub
	}
//根据外部状态进行逻辑处理
	public void operate(int extrinsic) {
		System.out.println("具体Flyweight:"+extrinsic);
	}
}
//UnsharedConcreteFlyweight是指那些不需要共享的Flyweight子类。因为Flyweight接口使共享成为可能,但他并不强制共享。
class UnsharedConcreteFlyweight extends Flyweight{
	public UnsharedConcreteFlyweight(String extrinsic) {
		super(extrinsic);
	}

	@Override
	public void operate(int extrinsic) {
		// TODO Auto-generated method stub
		System.out.println("不共享的具体Flyweight:"+extrinsic);
	}
}
//FlyweightFactory,是一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。
class FlyweightFactory{
	//定义一个池容器
	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.println("已有"+extrinsic+"直接从池中取");
	}else {
		flyweight=new ConcreteFlyweight(extrinsic);
		pool.put(extrinsic, flyweight);//放入池中
		System.out.println("创建"+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

网站共享代码(无外部状态的享元模式)

import java.util.HashMap;

abstract class WebSite{//共享部分
	public abstract void Use();
}
class ConcreteWebSite extends WebSite{//具体网站
	private String name="";
	public ConcreteWebSite(String name) {
		this.name=name;
	}
	public void Use() {
		System.out.println("网站分类:"+name);
	}
}
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();
		WebSite fy=f.GetWebSiteCategory("产品展示"); fy.Use();
		WebSite fz=f.GetWebSiteCategory("产品展示"); fz.Use();
		WebSite fl=f.GetWebSiteCategory("博客"); fl.Use();
		WebSite fm=f.GetWebSiteCategory("博客"); fm.Use();
		WebSite fn=f.GetWebSiteCategory("博客"); fn.Use();
		System.out.println("网站分类总数为"+f.GetWebSiteCount());
		}
}

结果为
网站分类:产品展示
网站分类:产品展示
网站分类:产品展示
网站分类:博客
网站分类:博客
网站分类:博客
网站分类总数为2

存在问题:这样写没有体现对象间的不同。

解决方案

import java.util.HashMap;
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);
}//参数user是在类WebSite外定义的一个类User,在方法Use调用时将它传递进来。
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

享元模式设计的重点就在分离变与不变。把一个对象的状态分成内部状态和外部状态,内部状态是不变的,外部状态是可变的。然后通过共享不变的部分,达到减少对象数量并节约内存的目的。
享元模式在什么情况下使用?
1、一个系统有大量的对象。
2、这些对象耗费大量的内存。
3、这些对象的状态中的大部分都可以外部化。
4、这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一个组都可以仅用一个对象代替。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值