结构型模式--享元模式

1. 享元模式的概述

    享元模式以共享的方式高效地支持大量细粒度对象的重用;享元对象能做到共享的关键是区分内部状态(Intrinsic State)和外部状态(Extrinsic State)

    1) 内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享,例如:字符的内容,不会随外部环境的变化而变化,无论在任何环境下,字符"a"始终是"a",不会变;

    2) 外部状态是随着环境改变而改变的,不可以共享的状态.享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候,再传入到享元对象内部,一个外部状态与另一个外部状态之间是相互独立的,如字符的颜色,可以在不同的地方有不同的颜色;字符的大小也是一样;而且字符的颜色和大小是两个独立的外部状态,它们可以独立变化,相互之间没有影响,客户端可以在使用时将外部状态注入享元对象中;

    由于区分了内部状态与外部状态,可以将具有相同内部状态的对象存储在享元池中,享元池中对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用,通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存呢中国实际上只存储一份

    3) 定义: 运用共享的技术有效的支持大量细粒度对象的复用,系统只使用少量的对象,而这些对象都很相似,状态变化都很小,可以实现对象的多次复用

   4)  结构图

        享元模式结构比较复杂,一般结合工厂模式一起使用,在其结构图中包含了一个享元工厂类

        

    5) 结构图中的角色

        1. Flyweight(抽象享元类):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)

          2. ConcreteFlyweight(具体享元类):实现了抽象享元类,在具体享元类中为内部状态提供了存储空间,可结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象

           3. UnsharedConcreteFlywight(非共享具体享元类): 并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要时可直接实例化

            4. FlyweightFactory(享元工厂类): 用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象储存在一个享元池中,享元池一般设计为一个存储"键值对"的集合,可结合工厂模式进行设计;当用户请求一个具体享元对象时,享元工厂提供一个储存在享元池中已创建的实例或者创建一个新的实例(若不存在的),返回新创建的实例并将其存储在享元池中

    6) 核心代码

package com.zach.pattern.flyweight;

import java.util.HashMap;

/**
 * 享元工厂类作用在于提供一个用于存储享元对象的享元池,当用户需要对象时,首先
 * 从享元池中获取,若不存在,则创建一个新的享元对象返给用户,并保存在享元池中
 * 
 * @author  Zach
 * @date 2018年7月10日
 * @title FlyweightFactory
 */
public class FlyweightFactory {
	
	//定义一个HashMap用于存储享元对象,实现享元池
	private HashMap flyweights = new HashMap<>();
	
	public Flyweight getFlyweight(String key) {
		
		if(flyweights.containsKey(key)){
			return (Flyweight)flyweights.get(key);
		}else {
			Flyweight fw = new ConcreteFlyweight();
			flyweights.put(key, fw);
			return fw;
		}
	}
}
package com.zach.pattern.flyweight;

public  class Flyweight {
	
	//内部状态作为成员变量,同一个享元对象其内部状态一致
	private String instrinsicState;

	public Flyweight() {
		// TODO Auto-generated constructor stub
	}

	public Flyweight(String instrinsicState) {
		this.instrinsicState = instrinsicState;
	}
	
	//外部状态在使用时有外部设置,不保存在享元对象中,即使是同一个对象,在每一次调用时可以传入不同的外部状态
	public void operation(String extrinsicState) {
		
	}
}

2. 案例

    1) 需求

                

    2) 实现方案

            

3) 代码实现

    

package com.zach.pattern.flyweight;
/**
 * 围棋棋子类:抽象享元类
 * 
 * @author  Zach
 * @date 2018年7月10日
 * @title IgoChessman
 */
public abstract class IgoChessman {
	
	public abstract String getColor();
	
	public void display() {
		System.out.println("棋子颜色: "+this.getColor());
	}
	
}

package com.zach.pattern.flyweight;
/**
 * 黑色棋子类:具体享元类
 * 
 * @author  Zach
 * @date 2018年7月10日
 * @title BlackIgoChessman
 */
public class BlackIgoChessman extends IgoChessman {

	@Override
	public String getColor() {
		// TODO Auto-generated method stub
		return "黑色";
	}

}

package com.zach.pattern.flyweight;
/**
 * 白色棋子类:具体享元类
 * 
 * @author  Zach
 * @date 2018年7月10日
 * @title BlackIgoChessman
 */
public class WhiteIgoChessman extends IgoChessman {

	@Override
	public String getColor() {
		// TODO Auto-generated method stub
		return "白色";
	}

}
package com.zach.pattern.flyweight;

import java.util.HashMap;

/**
 * 围棋棋子工厂类:享元工厂类,使用单例模式进行设计
 * 
 * @author  Zach
 * @date 2018年7月10日
 * @title IgoChessmanFactory
 */
public class IgoChessmanFactory {
	
	private static IgoChessmanFactory instance = new IgoChessmanFactory();
	private static HashMap ht;
	
	private IgoChessmanFactory(){
		ht = new HashMap<>();
		IgoChessman black,white;
		black = new BlackIgoChessman();
		ht.put("b", black);
		white = new WhiteIgoChessman();
		ht.put("w", white);
	}
	
	//返回享元工厂类唯一实例
	public static IgoChessmanFactory getInstance(){
		return instance;
	}
	
	//通过key来获取存储在HashMap中的享元对象
	public static IgoChessman getIgoChessman(String color){
		return (IgoChessman) ht.get(color);
	}
}

package com.zach.pattern.flyweight;
/**
 * 客户端类
 * 
 * @author  Zach
 * @date 2018年7月10日
 * @title Client
 */
public class Client {
	public static void main(String[] args) {
		IgoChessman b1,b2,b3,w1,w2;
		IgoChessmanFactory factory = IgoChessmanFactory.getInstance();
		
		b1 = factory.getIgoChessman("b");
		b2 = factory.getIgoChessman("b");
		b3 = factory.getIgoChessman("b");
		System.out.println("判断两颗黑子是否相同: "+(b1==b2));
		
		w1 = factory.getIgoChessman("w");
		w2 = factory.getIgoChessman("w");
		System.out.println("判断两颗白子是否相同: "+(w1==w2));
		
		//显示棋子
		b1.display();
		b2.display();
		b3.display();
		w1.display();
		w2.display();
	}
}

    执行结果:

判断两颗黑子是否相同: true
判断两颗白子是否相同: true
棋子颜色: 黑色
棋子颜色: 黑色
棋子颜色: 黑色
棋子颜色: 白色
棋子颜色: 白色

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值