这篇博客我来说一下享元模式。享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式的应用可以参考线程池或者数据库连接池,这些都符合如下情况
1、系统有大量相似对象。 2、需要缓冲池的场景。
享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
何时使用:
1、系统中有大量对象。
2、这些对象消耗大量内存。
3、这些对象的状态大部分可以外部化。
4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。
5、系统不依赖于这些对象身份,这些对象是不可分辨的。
也就是说按照内部状态分组的对象都可以看做一个对象,这样就可以将这一组对象由一个对象进行表示,同时只是需要修改外部状态就可以了。
下面来看一下视频中的例子,视频中的例子是将棋子按照颜色的不同进行分类,同时为不同的棋子设置位置。
这里面,颜色是棋子的内部属性,也就是可以共享的属性。而位置是私有的属性,也就是外部属性。
首先声明一个接口
public interface ChessFlyWeight {
void setColor(String c);
String getColor();
void display(Coordinate c);
}
其次是ConcreteFlyWeight具体享元类 ,为内部状态提供成员变量进行存储。
class ConcreteChess implements ChessFlyWeight {
private String color;
public ConcreteChess(String color) {
super();
this.color = color;
}
@Override
public void display(Coordinate c) {
System.out.println("棋子颜色:"+color);
System.out.println("棋子位置:"+c.getX()+"----"+c.getY());
}
@Override
public String getColor() {
return color;
}
@Override
public void setColor(String c) {
this.color = c;
}
可以看到这里面对内部状态进行声明同时对外部状态提供了修改的方法。
然后就是享元工厂类 的声明了,它负责创建并管理享元对象,享元池一般设计成键值对。
public class ChessFlyWeightFactory {
//享元池
private static Map<String,ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();
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;
}
}
}
测试如下
public class Client {
public static void main(String[] args) {
ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
System.out.println(chess1);
System.out.println(chess2);
System.out.println("增加外部状态的处理===========");
chess1.display(new Coordinate(10, 10));
chess2.display(new Coordinate(20, 20));
}
}
通过颜色来实现对于棋子的获取,通过注入坐标来实现位置的修改。
其实这很像我们的数据库连接池的使用,所有的连接都是很类似的,如果我们每次连接数据库都开启一个新的连接,那么就会十分占用内存资源。同时也会造成很多连接的空闲和浪费,所以系统就对若干个连接池进行维护,就形成了连接池。只需要在每次获取连接池的时候进行外部状态修改即可