设计模式(10):享元模式

一.核心:

  • 享元模式以共享的方式高效地支持大量细粒度对象的重用。
  • 享元对象能做到共享的关键是区分了内部状态和外部状态。
    • 内部状态: 可以共享,不会随环境变化而改变。
    • 外部状态: 不可以共享,会随环境变化而改变。

二.场景:

  • 内存属于稀缺资源,不要随便浪费。如果有很多个相同或相似的对象,我们可以通过享元模式,节省内存。

三.角色组成

  • 抽象享元角色(FlyWeight): 享元对象抽象基类或者接口,同时定义出对象的外部状态和内部状态的接口或实现;
  • 具体享元角色(ConcreteFlyWeight): 抽象享元类的实现
  • 享元工厂(FlyWeightFactory): 维护一个享元对象的池,内部一般使用Map存储已经创建的享元对象

四.开发中应用的场景:

  • 享元模式由于其共享的特性,可以在任何"池"中操作,比如:线程池、数据库连接池
  • String类的设计也是享元模式
  • Integer的值在-128~127内也是享元模式

五.优缺点:

  • 优点:
    • 极大减少内存中对象的数量;
    • 相同或相似对象内存中只存一份,极大的节约资源,提高系统性能;
    • 外部状态相对独立,不影响内部状态。
  • 缺点:
    • 模式较复杂,使程序逻辑复杂化;
    • 为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态使运行时间变长。用时间换取了空间。

六.以围棋为例代码实现

1.举例:

  • 我们知道每个围棋棋子都是一个对象,有这些属性:颜色、形状、大小和位置,其中颜色、形状、大小都是一样的,只有位置不一样。这些相同的属性可以共享,我们称它为内部状态;而位置每个棋子都不一样,不能共享,我们称它为外部状态。

2.代码实现

    • (1)抽象享元类
java 复制代码
/**
 * 抽象享元类
 */
public interface ChessFlyWeight {
	void  setColor(String c); //设置颜色
	String  getColor(); //获得颜色
	void display(Doordinate c);//显示位置
}
    • (2)具体享元类
java 复制代码
/**
 * 具体享元类
 */
class ConcreteChess implements ChessFlyWeight{
	//颜色 共享
	private String color;
	public ConcreteChess(String color) {
		this.color = color;
	}
	@Override
	public void setColor(String color) {
		this.color=color;
	}
	@Override
	public String getColor() {
		return color;
	}
	@Override
	public void display(Doordinate c) {
		System.out.println("棋子的颜色:"+color+"\t"+"当前棋子的位置:"+c.getX()+"-->"+c.getY());
	}
}
    • (3)外部状态
java 复制代码
/**
 * 外部状态(棋子位置类)UnSharedConcreteFlyWeight
 */
public class Doordinate {
	private int x,y;
	public Doordinate() {
	}
	public Doordinate(int x, int y) {
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	public void setX(int x) {
		this.x = x;
	}
	public void setY(int y) {
		this.y = y;
	}
}
    • (4)享元工厂
java 复制代码
/**
 * 享元工厂
 */
public class ChessFlyWeightFactory{
	private static Map<String ,ChessFlyWeight> map=new HashMap();
	public static ChessFlyWeight getChess(String color){
		if(map.get(color)!=null){
			return map.get(color);
		}else{
			ChessFlyWeight cfw=new ConcreteChess(color);
			map.put(color, cfw);
			return cfw;
		}		
	}	
}
    • (4)调用
java 复制代码
/**
 * 享元模式
 */
public class App {
	public static void main(String[] args) {
		ChessFlyWeight chess1=ChessFlyWeightFactory.getChess("黑色");
		ChessFlyWeight chess2=ChessFlyWeightFactory.getChess("黑色");
		System.out.println(chess1==chess2);
		
		System.out.println("增加外部状态的处理");		
		chess1.display(new Doordinate(10,10));
		chess2.display(new Doordinate(20,20));
		System.out.println(chess1==chess2);
	}
}

更多设计模式学习:

设计模式(1):介绍

设计模式(2):单例模式

设计模式(3):工厂模式

设计模式(4):建造者模式

设计模式(5):原型模式

设计模式(6):桥接模式

设计模式(7):装饰器模式

设计模式(8):组合模式

设计模式(9):外观模式

设计模式持续更新中...

相关推荐
敲击Time3 分钟前
【华为OD机考真题】- 星际篮球争霸赛(Java)
java·华为od
simple_ssn13 分钟前
17153.班级活动(java)
java·开发语言·算法
xcLeigh34 分钟前
JAVA实现好看的俄罗斯方块小游戏(附源码)
java·开发语言·小游戏·俄罗斯方块
用键盘当武器的秋刀鱼36 分钟前
bug修改模板(日志)
java·开发语言·bug
sakoba1 小时前
SpringMVC
java·学习
钢板兽1 小时前
力扣hot100——子串、普通数组、矩阵
java·后端·算法·leetcode·面试·矩阵
香菇滑稽之谈1 小时前
状态模式的C++实现示例
c++·设计模式·状态模式
紫气东来,茉上花开1 小时前
java如何在linux服务器创建文件excel并把循环插入每一行的后端查出来的数据,每天新建一个excel带时间的
java·linux·服务器
奔跑的废柴2 小时前
LeetCode 513. 找树左下角的值 java题解
java·算法·leetcode
青云交3 小时前
Java 大视界 -- Java 大数据在智能安防视频摘要与检索技术中的应用(128)
java·大数据·图像处理·机器学习·视频检索·智能安防·视频摘要