一.核心:
- 享元模式以共享的方式高效地支持大量细粒度对象的重用。
- 享元对象能做到共享的关键是区分了内部状态和外部状态。
- 内部状态: 可以共享,不会随环境变化而改变。
- 外部状态: 不可以共享,会随环境变化而改变。
二.场景:
- 内存属于稀缺资源,不要随便浪费。如果有很多个相同或相似的对象,我们可以通过享元模式,节省内存。
三.角色组成
- 抽象享元角色(FlyWeight): 享元对象抽象基类或者接口,同时定义出对象的外部状态和内部状态的接口或实现;
- 具体享元角色(ConcreteFlyWeight): 抽象享元类的实现
- 享元工厂(FlyWeightFactory): 维护一个享元对象的池,内部一般使用Map存储已经创建的享元对象
四.开发中应用的场景:
- 享元模式由于其共享的特性,可以在任何"池"中操作,比如:线程池、数据库连接池
- String类的设计也是享元模式
- Integer的值在-128~127内也是享元模式
五.优缺点:
- 优点:
- 极大减少内存中对象的数量;
- 相同或相似对象内存中只存一份,极大的节约资源,提高系统性能;
- 外部状态相对独立,不影响内部状态。
- 缺点:
- 模式较复杂,使程序逻辑复杂化;
- 为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态使运行时间变长。用时间换取了空间。
六.以围棋为例代码实现
-
1.举例:
- 我们知道每个围棋棋子都是一个对象,有这些属性:颜色、形状、大小和位置,其中颜色、形状、大小都是一样的,只有位置不一样。这些相同的属性可以共享,我们称它为内部状态;而位置每个棋子都不一样,不能共享,我们称它为外部状态。
-
2.代码实现
-
- (1)抽象享元类
/*** 抽象享元类*/
public interface ChessFlyWeight {void setColor(String c); //设置颜色String getColor(); //获得颜色void display(Doordinate c);//显示位置
}
-
- (2)具体享元类
/*** 具体享元类*/
class ConcreteChess implements ChessFlyWeight{//颜色 共享private String color;public ConcreteChess(String color) {this.color = color;}@Overridepublic void setColor(String color) {this.color=color;}@Overridepublic String getColor() {return color;}@Overridepublic void display(Doordinate c) {System.out.println("棋子的颜色:"+color+"\t"+"当前棋子的位置:"+c.getX()+"-->"+c.getY());}
}
-
- (3)外部状态
/*** 外部状态(棋子位置类)UnSharedConcreteFlyWeight*/
public class Doordinate {private int x,y;public Doordinate() {}public Doordinate(int x, int y) {this.x = x;this.y = y;}public int getX() {return x;}public int getY() {return y;}public void setX(int x) {this.x = x;}public void setY(int y) {this.y = y;}
}
-
- (4)享元工厂
/*** 享元工厂*/
public class ChessFlyWeightFactory{private static Map<String ,ChessFlyWeight> map=new HashMap();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;} }
}
-
- (4)调用
/*** 享元模式*/
public class App {public static void main(String[] args) {ChessFlyWeight chess1=ChessFlyWeightFactory.getChess("黑色");ChessFlyWeight chess2=ChessFlyWeightFactory.getChess("黑色");System.out.println(chess1==chess2);System.out.println("增加外部状态的处理"); chess1.display(new Doordinate(10,10));chess2.display(new Doordinate(20,20));System.out.println(chess1==chess2);}
}
更多设计模式学习:
设计模式(1):介绍
设计模式(2):单例模式
设计模式(3):工厂模式
设计模式(4):建造者模式
设计模式(5):原型模式
设计模式(6):桥接模式
设计模式(7):装饰器模式
设计模式(8):组合模式
设计模式(9):外观模式
设计模式持续更新中…