1.定义
-
享元模式(Flyweight)通过与其他类似对象共享数据来减小内存占用。
-
享元模式的两种状态:
- 内部状态:不会随着环境的改变而改变的可共享部分;
- 外部状态:会随环境改变而改变的不可共享的部分。
2.结构
2.1 UML类图
2.2 角色
- Flyweight 抽象享元角色:所有具体享元类的父类,规定一些需要实现的公共接口
- ConcreteFlyweight 具体享元角色:抽象享元角色的具体实现类,并实现了抽象享元角色规定的方法。
- UnsharedConcreteFlyweight 不可共享的享元角色,一般不会出现在享元工厂中。
- FlyweightFactory 享元工厂角色:负责创建和管理享元角色。
3.实现
/**
* Flyweight享元角色
*/
abstract class Human {
protected String name;
public void setName(String name) {
this.name = name;
}
abstract void attack();
}
/**
* ConcreteFlyweight 具体享元角色
*/
class Fighter extends Human {
@Override
public void attack() {
System.out.println(name + " 开始攻击......");
}
}
/**
* UnsharedConcreteFlyweight 不可共享的享元角色
*/
class IronMan extends Human {
public IronMan(String name) {
this.name = name;
}
@Override
void attack() {
System.out.println(name + "开始进攻。。。");
}
}
/**
* FlyweightFactory 享元工厂角色
*/
class FighterFactory {
private Map<String, Human> pool = new HashMap<>();
public Human getHuman(String name) {
Human human = pool.get(name);
if (human == null) {
human = new Fighter();
human.setName("创建 " + name);
pool.put(name, human);
} else {
human.setName("从池中取出 " + name);
}
return human;
}
}
/**
* 测试类
*/
public class FlyweightDemo {
public static void main(String[] args) {
FighterFactory fighterFactory = new FighterFactory();
fighterFactory.getHuman("草薙京").attack();
fighterFactory.getHuman("不知火舞").attack();
fighterFactory.getHuman("雅典娜").attack();
fighterFactory.getHuman("草薙京").attack();
fighterFactory.getHuman("不知火舞").attack();
// 不可共享的享元角色,单独创建,不会出现在享元工厂中。
Human ironMan = new IronMan("创造 钢铁侠");
ironMan.attack();
}
}
4.总结
4.1 优点
- 减少了对象的创建,降低系统的内存。
- 外部状态不会影响内部状态,可以在不同环境下进行共享。
4.2 缺点
- 增加了系统的复杂度,需要分离出外部状态和内部状态。
4.3 应用场景
- 当系统中有大量对象,并且这些对象会消耗大量内存,可使用享元模式。
- String常量池:在JAVA 中创建String,从缓存池中获取,若没有则创建一个字符串保存在字符串缓存池里面。
- 数据库的数据池。
本人才疏学浅,若有错,请指出,谢谢!
如果你有更好的建议,可以留言我们一起讨论,共同进步!
衷心的感谢您能耐心的读完本篇博文!