设计模式之享元模式笔记
- 说明
- Flyweight(享元)
- 目录
- 享元模式示例类图
- 抽象图形类
- I图形类
- L图形类
- O图形类
- 工厂类
- 测试类
说明
记录下学习设计模式-享元模式的写法。JDK使用版本为1.8版本。
Flyweight(享元)
意图:运用共享技术有效地支持大量细粒度的对象。
结构:
其中:
- Flyweight描述一个接口,通过这个接口Flyweight可以接受并作用于外部状态。
- ConcreteFlyweight实现Flyweight接口,并为内部状态(如果有)增加存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的,即它必须独立于ConcreteFlyweight对象的场景。
- 并非所有的Flyweight子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。在Flyweight对象结构的某些层次,UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。
- FlyweightFactory创建并管理Flyweight对象;确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者在不存在时创建一个实例。
- Client维持一个对Flyweight的引用:计算或存储一个或多个Flyweight的外部状态。
适用性:
- 一个应用程序使用了大量的对象。
- 完全由于使用大量的对象,造成很大的存储开销。
- 对象的大多数状态都可变为外部状态。
- 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
- 应用程序不依赖于对象标识。由于Flyweight对象可以被共享,所以对于概念上明显有别的对象,标识测试将返回真值。
使用场景:
- 一个系统有大量相同或者相似的对象,造成内存的大量耗费。
- 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
- 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。
目录
享元模式示例类图
以该UML类图实现享元模式示例。
抽象图形类
package com.example.deesign_patterns.flyweight;//抽象享元角色
public abstract class AbstractBox {//获取图形的方法public abstract String getShape();//显示图形及颜色public void display(String color){System.out.println("方块形状:"+getShape()+",方块颜色:"+color);}
}
I图形类
package com.example.deesign_patterns.flyweight;//I图形类(具体享元角色)
public class IBox extends AbstractBox{@Overridepublic String getShape() {return "I";}
}
L图形类
package com.example.deesign_patterns.flyweight;//L图形类(具体享元角色)
public class LBox extends AbstractBox{@Overridepublic String getShape() {return "L";}
}
O图形类
package com.example.deesign_patterns.flyweight;//O图形类(具体享元角色)
public class OBox extends AbstractBox{@Overridepublic String getShape() {return "O";}
}
工厂类
package com.example.deesign_patterns.flyweight;import java.util.HashMap;//工厂类,将该类设计为单例
public class BoxFactory {private HashMap<String,AbstractBox> map;//使用单例模式-饿汉式静态成员变量方式private static BoxFactory factory=new BoxFactory();//在构造方法中进行初始化操作public BoxFactory() {map=new HashMap<String,AbstractBox>();map.put("I",new IBox());map.put("L",new LBox());map.put("O",new OBox());}//提供一个方法获取该工厂类对象public static BoxFactory getInstance(){return factory;}//根据名称获取图形对象public AbstractBox getShape(String name){return map.get(name);}
}
测试类
package com.example.deesign_patterns.flyweight;//测试类
public class Client {public static void main(String[] args) {//获取I图形对象AbstractBox box1 = BoxFactory.getInstance().getShape("I");box1.display("灰色");//获取L图形对象AbstractBox box2 = BoxFactory.getInstance().getShape("L");box2.display("绿色");//获取O图形对象AbstractBox box3 = BoxFactory.getInstance().getShape("O");box3.display("灰色");//获取O图形对象AbstractBox box4 = BoxFactory.getInstance().getShape("O");box4.display("红色");System.out.println("两次获取到的O图形对象是否是同一个对象:"+(box3==box4));}
}
好处:
- 极大减少内存中相似或相同对象数量,节约系统资源,提供系统性能。
- 享元模式中的外部状态相对独立,且不影响内部状态。
缺点:
为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂。