享元模式是一种结构型设计模式,旨在通过共享对象来最大程度地减少内存使用和提高性能。它主要用于减少创建对象的数量,节省内存和提高性能。
该模式通过共享相似对象之间的公共部分来减少内存占用。当需要创建大量相似对象时,通过重用已存在的相似对象,而不是每次都新建一个对象来节省内存。这个被共享的对象称为享元(Flyweight),包含了对象的共享状态和非共享状态。共享状态是可以被多个对象共享的部分,而非共享状态是对象独有的部分。
通过分离内部状态(不变且可共享)和外部状态(变化且不可共享),享元模式允许在运行时共享许多细粒度对象,从而提高系统的性能和效率。典型的例子是文本编辑器中的字符对象,大量的字符对象在外观上是相似的,例如,大写字母 “A” 的字形和颜色通常是相同的,所以可以使用享元模式来共享这些共同的特性,从而节省内存。
当涉及中国象棋时,可以使用享元模式来模拟棋子。每个棋子(如将、车、马等)都有自己的共享属性(例如颜色、类型),而位置是每个棋子独有的非共享属性。
首先,定义棋子类 ChessPiece:
// 棋子类
public class ChessPiece {
private String type; // 共享属性 - 棋子类型
private String color; // 共享属性 - 棋子颜色
private int x, y; // 非共享属性 - 棋子位置
public ChessPiece(String color, String type) {
this.type = type;
this.color = color;
this.x = 0; // 默认位置
this.y = 0;
}
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
}
public void display() {
System.out.println("象棋: " + color + " " + type + " 的位置 (" + x + ", " + y + ")");
}
}
然后,创建一个工厂类 ChessPieceFactory 来管理棋子的共享:
// 棋子工厂类
public class ChessPieceFactory {
private static final Map<String, ChessPiece> pieces = new HashMap<>();
public static ChessPiece getChessPiece(String color, String type) {
String key = color + "_" + type;
if (!pieces.containsKey(key)) {
pieces.put(key, new ChessPiece(color, type));
}
return pieces.get(key);
}
}
接下来,使用示例:
public class FlyweightChessDemo {
public static void main(String[] args) {
ChessPiece piece1 = ChessPieceFactory.getChessPiece("红", "炮");
piece1.setPosition(0, 3);
piece1.display();
ChessPiece piece2 = ChessPieceFactory.getChessPiece("红", "车");
piece2.setPosition(1, 3);
piece2.display();
ChessPiece piece3 = ChessPieceFactory.getChessPiece("黑", "马");
piece3.setPosition(0, 6);
piece3.display();
ChessPiece piece4 = ChessPieceFactory.getChessPiece("黑", "卒");
piece4.setPosition(3, 5);
piece4.display();
}
}
运行结果:
象棋: 红 炮 的位置 (0, 3)
象棋: 红 车 的位置 (1, 3)
象棋: 黑 马 的位置 (0, 6)
象棋: 黑 卒 的位置 (3, 5)
在这个例子中,ChessPieceFactory 管理着共享的棋子对象。当需要创建棋子时,首先检查该类型和颜色的棋子是否已经存在,如果存在则直接返回已存在的棋子对象,否则创建新的棋子对象。这样可以实现共享相同类型和颜色的棋子,减少了棋子对象的创建数量,节省了内存空间。
享元模式的优点和缺点如下所示:
优点:
缺点:
综上所述,享元模式在合适的场景下能够显著减少内存消耗和提高性能,但需要注意在设计和实现时平衡可维护性和复杂性,避免引入过多的共享状态以及可能导致的对象状态不一致问题。