写在前面
本文看下一种结构型设计模式,享元模式。
1:介绍
1.1:什么时候使用享元模式
当程序需要大量的重复对象,并且这些大量的重复对象只有部分属性不相同,其他都是相同的时候,就可以考虑使用享元设计模式设计模式来实现。典型的如围棋游戏中的棋子,除了颜色和位置不同外,其他都相同。射击游戏中的子弹,除了大小,型号,杀伤力等不同外,其他都相同。
1.2:UML类图
享元设计模式,包含如下元素:
1:Flyweight
定义享元对象的公共操作
2:ConcreteFlyweight
具体的享元对象
3:FlyweightFactory
享元对象工厂,负责生产享元对象,方便客户端获取享元对象的同时,也可以缓存享元对象,防止因为创建过多的对象而导致内存溢出等问题(想一下射击游戏,用户如果是用机关枪一直突突突,得创建多少对象啊)
UML图如下:
另外,享元设计模式分为内部状态和外部状态,如围棋游戏,棋子的黑色和白色,就是内部状态,在对象的内部定义和维护,是可以共享的,但是落子的位置则是各不相同的,就是外部状态,需要外部传入。如果是工作中认为场景适合使用享元设计模式则一定要考虑清楚内部状态和外部状态
的问题。
2:实例
源码 。
2.1:场景
围棋游戏,创建游戏中的黑子和白子。
2.2:程序
- 享元接口
java
public interface Chess {
// 绘制棋子(落子,走一步棋)
// 位置,外部状态,由外部传入
void draw(int x,int y);
}
- 内部状态枚举
java
public enum Color {
BLACK("黑色"), WHITE("白色");
private String name;
// 默认就是private的,并且不能反射,暴力也不行
Color(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAlias() {
return this.name;
}
}
- 具体享元类
黑子和白子类:
java
//黑棋
public class BlackChess implements Chess {
// 内部状态,共享
private final Color color = Color.BLACK;
private final String sharp = "圆形";
public Color getColor() {
return color;
}
// 外部状态
@Override
public void draw(int x, int y) {
System.out.println(String.format("%s%s棋子置于(%d,%d)处", sharp, color.getAlias(), x, y));
}
}
//白棋
public class WhiteChess implements Chess {
//内部状态,共享
private final Color color = Color.WHITE;
private final String sharp = "圆形";
public Color getColor() {
return color;
}
@Override
public void draw(int x, int y) {
System.out.println(String.format("%s%s棋子置于(%d,%d)处", sharp, color.getAlias(), x, y));
}
}
- 享元工厂类
java
public class ChessFactory {
private static final Map<Color, Chess> chessMap = new HashMap<>();
public static Chess getChess(Color color) {
Chess chess = chessMap.get(color);
if (chess == null) {
chess = color == Color.WHITE ? new WhiteChess() : new BlackChess();
chessMap.put(color, chess);
}
return chess;
}
}
- 测试
java
public class FlyweightClient {
@Test
public void playChess() {
//下黑子
Chess backChess1 = ChessFactory.getChess(Color.BLACK);
backChess1.draw(2, 5);
//下白子
Chess whiteChess = ChessFactory.getChess(Color.WHITE);
whiteChess.draw(3, 5);
//下黑子
Chess backChess2 = ChessFactory.getChess(Color.BLACK);
backChess2.draw(2, 6);
System.out.println(String.format("backChess1:%d | backChess2:%d | whiteChess:%d",
backChess1.hashCode(), backChess2.hashCode(), whiteChess.hashCode()));
}
}
运行:
圆形黑色棋子置于(2,5)处
圆形白色棋子置于(3,5)处
圆形黑色棋子置于(2,6)处
backChess1:1327763628 | backChess2:1327763628 | whiteChess:1915503092
Process finished with exit code 0