再战设计模式之享元模式
Posted bj-xiaodao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了再战设计模式之享元模式相关的知识,希望对你有一定的参考价值。
享元模式
场景:
内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的 对象,我们可以通过享元模式,节省内存.
核心:
本质:享元模式以共享的方式高效地支持大量细粒度对象的重用
类图的看比较复杂.我们来剖析下
享元对象能做到共享的关键是区分了内部状态和外部状态
内部状态:可以共享,不会随环境变化而改变
外部状态:不可以共享,会随环境变化而改变
现在有个需求,需要为围棋设置一个程序,那么围棋的棋子改如何设计?总共有很多黑子和白子,难道我们需要为每一个棋子生成一个对象吗?
显然这样的设计是不合理的.这个时候我们就可以用到享元模式!
类图:如下
chessFlyWeight:是一个接口,声明了一些公共的方法,这些方法可以向外提供内部状态,以及设置外部的状态
ChessFlyWeightImpl: 是一个享元对象的实例,可以存储内部状态(因为可以共享) ,可以获取外部状态的属性.如 x y
ChessCoordinateConcrete: 是享元对象的外部状态不可以共享,,可以随意设置
ChessFlyWeightFactory : 就是通过内部状态.获取对象..就像我们平时用的缓存一样.我把他设置成单例的了.
client: 可以具体的调用这里就不多说了.
代码:
/** * 享元类 * @Created by xiaodao */ public interface ChessFlyWeight { void setColor(String color ); String getColor(); void display(ChessCoordinateConcrete c ); } /** * 为内部对象,提供享元存储.!! * @Created by xiaodao */ public class ChessFlyWeightImpl implements ChessFlyWeight { private String color; public ChessFlyWeightImpl(String color) { this.color = color; } public void setColor(String color) { this.color = color; } public String getColor() { return this.color; } public void display(ChessCoordinateConcrete c) { System.out.println("chess‘s color = "+ color); System.out.println("chess;s position x = "+ c.getX() +"----- y = "+ c.getY()); } } /** * 不可共享的外部结构 * @Created by xiaodao */ public class ChessCoordinateConcrete { private int x,y; public ChessCoordinateConcrete(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } } /** * 享元 工厂 返回 接口... * @Created by xiaodao */ public class ChessFlyWeightFactory { private static ChessFlyWeightFactory instance= new ChessFlyWeightFactory(); private static HashMap<String,ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>(); public ChessFlyWeight getChess(String color){ if(map.get(color) !=null){ return map.get(color); }else{ ChessFlyWeight chessFlyWeight = new ChessFlyWeightImpl(color); map.put(color,chessFlyWeight); return map.get(color); } } private ChessFlyWeightFactory() { } public static ChessFlyWeightFactory getInstance(){ return instance; } }
/** * @Created by xiaodao */ public class Client { public static void main(String[] args) { ChessFlyWeightFactory c = ChessFlyWeightFactory.getInstance(); ChessFlyWeight chess1 = c.getChess("黑色"); chess1.display(new ChessCoordinateConcrete(10,20)); ChessFlyWeight chess2 = c.getChess("黑色"); System.out.println("-----------------"); chess2.display(new ChessCoordinateConcrete(20,30)); System.out.println(chess1); System.out.println(chess2); } } 获取到的结果: chess‘s color = 黑色 chess;s position x = 10----- y = 20 ----------------- chess‘s color = 黑色 chess;s position x = 20----- y = 30 [email protected] [email protected]
这样的运行之后..我们就可以获取到同一个对象,但是他的外部不可共享的属性确不一样..这就可以节省很多内存空间.
角色:
享元模式实现:
– FlyweightFactory享元工厂类
• 创建并管理享元对象,享元池一般设计成键值对
– FlyWeight抽象享元类
• 通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象 的内部状态,设置外部状态。
– ConcreteFlyWeight具体享元类
• 为内部状态提供成员变量进行存储
– UnsharedConcreteFlyWeight非共享享元类
• 不能被共享的子类可以设计为非共享享元类
总结:
享元模式,我们在工作中很少用,写起来比较复杂.维护也不好维护,但是我们还是需要了解,这样对阅读源码是比较友好的.
优点:
- 极大的减少了内存中的对象数量
- 相同或者相似的对象内存中只有一份,节省空间
- 外部状态相对独立,不影响内部的属性
缺点:
- 模式比较复杂.看上面的类图就知道,感觉不够清晰,是程序逻辑复杂化
- 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。 用时间换取了空间
JDK或者项目中的使用
string 也是使用的享元模式,共享常量池.
integer: 中也使用了
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
Integer a = Integer.valueOf(100); Integer b = 100; Integer c =Integer.valueOf(1000); Integer d = Integer.valueOf(1000); System.out.println(a==b); System.out.println(c==d);
true
false
integer 最小是-128 最大是127 在缓存中,当然也可以设置.也是使用的享元模式
数据连接池还有各种pool 也是使用的这个模式
以上是关于再战设计模式之享元模式的主要内容,如果未能解决你的问题,请参考以下文章