闲话
今天是周末,本来想偷一下懒,想想还是看一节设计模式吧
写的不好,欢迎大家一起讨论~
基本要点
1、使用场景:内存属于稀缺资源,如果有很多个完全相同或相似的对象,我们可以通过享元模式,节省内存
2、核心
-
以共享的方式支持大量细粒度对象的重用
-
享元对象能做到共享的关键是区分了内部状态和外部状态
内部状态:可以共享,不会随环境变化而改变
外部状态:不可以共享,会随环境变化而改变
举例围棋软件来说
每个棋子都可以看成一个对象,颜色、形状、大小都能称为内部状态,因为这些是可共享的
但是位置每一个棋子都是独一无二的,是不可共享的,所以是外部状态
3、享元模式的实现
- FlyweightFactory享元工厂类:创建并管理享元对象,享元池一般设计成键值对(可以理解为Map)
- FlyWeight抽象享元对象:通常是一个接口或抽象类,用于声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态,例子中的棋子就可以看成这个
- ConcreteFlyWeight具体享元类:将内部状态放在这,为内部状态提供成员变量进行存储
- UnsharedConcreteFlyWeight非共享享元类:将外部状态放在这,不能被共享的子类可以设计成非共享享元类
4、享元模式优缺点
优点:极大减少了内存中对象的数量,节约系统资源,而且外部状态相对独立,不影响内部状态。
缺点:模式较为复杂,使程序逻辑复杂化;为了节省内存,共享了内部状态,分离出了外部状态,而读取外部状态时间较长,为了空间牺牲了时间。
实现代码
我们以上面的围棋系统为例子
首先,我们创建享元类和具体享元类
/**
* 享元类,即FlyWeight抽象享元对象
*/
public interface ChessFlyWeight {
// 获取棋子颜色(获取内部状态)
String getColor();
// 设置棋子坐标(设置外部状态)
void display(Coordinate coordinate);
}
/**
* ConcreteFlyWeight具体享元类:将内部状态放在这,提供成员变量进行存储
*/
class ChessConcreteFlyWeight implements ChessFlyWeight {
// 为内部状态提供成员变量进行存储
private String color;
public ChessConcreteFlyWeight(String color) {
this.color = color;
}
@Override
public String getColor() {
return color;
}
@Override
public void display(Coordinate coordinate) {
System.out.println("棋子颜色:" + color);
System.out.println("棋子坐标:x= " + coordinate.getX() + "y=" + coordinate.getY());
}
}
创建非共享享元类,将外部状态放在这里
/**
* 外部状态相关类,UnsharedConcreteFlyWeight非共享享元类
*/
public class Coordinate {
// 棋子的坐标是外部状态
private int x,y;
public Coordinate(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;
}
}
创建享元工厂
import java.util.HashMap;
import java.util.Map;
/**
* 享元工厂
*/
public class ChessFlyWeightFactory {
// 享元池
private static Map<String, ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();
// 根据颜色获取棋子对象
public static ChessFlyWeight getChess(String color) {
// 如果有符合当前颜色要求的棋子对象,那就返回
if (null != map.get(color)) {
return map.get(color);
} else {
// 如果没有符合的对象就创建新的棋子对象,然后将其放入享元池中,在返回
ChessFlyWeight chess = new ChessConcreteFlyWeight(color);
map.put(color, chess);
return chess;
}
}
}
模拟客户端
public class Client {
public static void main(String[] args) {
ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
// chess1创建时,享元池里面并没有黑色棋子,所以创建了一个,获取chess2时,有了黑色棋子,所以可以直接去拿之前创建的那个对象
System.out.println(chess1);
System.out.println(chess2);
System.out.println("增加外部状态处理===========");
chess1.display(new Coordinate(10, 10));
chess2.display(new Coordinate(20, 20));
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136812.html