《Head First 设计模式》笔记19-享元模式
定义
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。
由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式(蝇量模式),它是一种对象结构型模式。
在了解享元模式之前我们先要了解两个概念:内部状态、外部状态。
内部状态:在享元对象内部不随外界环境改变而改变的共享部分。
外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态。
由于享元模式区分了内部状态和外部状态,所以我们可以通过设置不同的外部状态使得相同的对象可以具备一些不同的特性,而内部状态设置为相同部分。在我们的程序设计过程中,我们可能会需要大量的细粒度对象来表示对象,如果这些对象除了几个参数不同外其他部分都相同,这个时候我们就可以利用享元模式来大大减少应用程序当中的对象。如何利用享元模式呢?这里我们只需要将他们少部分的不同的部分当做参数移动到类实例的外部去,然后再方法调用的时候将他们传递过来就可以了。这里也就说明了一点:内部状态存储于享元对象内部,而外部状态则应该由客户端来考虑。
模式结构
享元模式存在如下几个角色:
- Flyweight: 抽象享元类。所有具体享元类的超类或者接口,通过这个接口,Flyweight 可以接受并作用于外部状态。
- ConcreteFlyweight: 具体享元类。指定内部状态,为内部状态增加存储空间。
- UnsharedConcreteFlyweight: 非共享具体享元类。指出那些不需要共享的 Flyweight 子类。
- FlyweightFactory: 享元工厂类。用来创建并管理 Flyweight 对象,它主要用来确保合理地共享 Flyweight,当用户请求一个 Flyweight 时,FlyweightFactory 就会提供一个已经创建的 Flyweight 对象或者新建一个(如果不存在)。
示例代码
场景:假如我们有一个绘图的应用程序,通过它我们可以出绘制各种各样的形状、颜色的图形,那么这里形状和颜色就是内部状态了,通过享元模式我们就可以实现该属性的共享了。如下:
首先是形状类:Shape.java。它是抽象类,只有一个绘制图形的抽象方法。
public abstract class Shape {
public abstract void draw();
}
然后是绘制圆形的具体类。Circle.java
public class Circle extends Shape{
private String color;
public Circle(String color){
this.color = color;
}
public void draw() {
System.out.println("画了一个" + color +"的圆形");
}
}
再是享元工厂类。FlyweightFactory
public class FlyweightFactory{
static Map<String, Shape> shapes = new HashMap<String, Shape>();
public static Shape getShape(String key){
Shape shape = shapes.get(key);
//如果shape==null,表示不存在,则新建,并且保持到共享池中
if(shape == null){
shape = new Circle(key);
shapes.put(key, shape);
}
return shape;
}
public static int getSum(){
return shapes.size();
}
}
最后是客户端程序:Client.java
public class Client {
public static void main(String[] args) {
Shape shape1 = FlyweightFactory.getShape("红色");
shape1.draw();
Shape shape2 = FlyweightFactory.getShape("灰色");
shape2.draw();
Shape shape3 = FlyweightFactory.getShape("灰色");
shape3.draw();
System.out.println("一共绘制了"+FlyweightFactory.getSum()+"中颜色的圆形");
}
}
优缺点
优点
- 享元模式的优点在于它可以极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份。
- 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
缺点
- 享元模式使得系统更加复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
- 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。
模式扩展
单纯享元模式和复合享元模式
- 单纯享元模式:在单纯享元模式中,所有的享元对象都是可以共享的,即所有抽象享元类的子类都可共享,不存在非共享具体享元类。
- 复合享元模式:将一些单纯享元使用组合模式加以组合,可以形成复合享元对象,这样的复合享元对象本身不能共享,但是它们可以分解成单纯享元对象,而后者则可以共享。
享元模式与其他模式的联用
- 在享元模式的享元工厂类中通常提供一个静态的工厂方法用于返回享元对象,使用简单工厂模式来生成享元对象。
- 在一个系统中,通常只有唯一一个享元工厂,因此享元工厂类可以使用单例模式进行设计。
- 享元模式可以结合组合模式形成复合享元模式,统一对享元对象设置外部状态。
参考
http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/flyweight.html
https://blog.csdn.net/chenssy/article/details/11850107
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:《Head First 设计模式》笔记19-享元模式
文章字数:1.4k
本文作者:Bin
发布时间:2018-08-02, 23:17:57
最后更新:2019-08-06, 00:07:35
原始链接:http://coolview.github.io/2018/08/02/Head-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E3%80%8AHead-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%8B%E7%AC%94%E8%AE%B019-%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。