您当前的位置:首页 > 计算机 > 编程开发 > 设计模式

【设计模式】31.结构型模式-享元模式(Flyweight)

时间:02-01来源:作者:点击数:

一、描述

这是个很有意思的模式。它是通过共享技术来有效地支持大量细粒度对象的复用。

角色

(1)Flyweight:描述一个接口,通过这个接口flyweight可以接受并作用于外部状态
(2)ConcreteFlyweight:实现Flyweight接口,并为内部状态增加存储空间。ConcreteFlyweight对象必须是共享的。它所存储的状态必须是内部的。
(3)FlyweightFactory:创建并管理Flyweight对象。确保合理地共享flyweight。当用户请求一个flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个
(4)Client:维持一个对flyweight的引用。计算或存储一个flyweight的外部状态。

类图

在这里插入图片描述
享元模式的特点有两个
(1)内在状态:用于创建对象。
(2)外在状态:外界传给实例的参数,用于实例执行某些方法。

如何理解享元模式?

刚开始看享元模式,这个模式感觉和单例模式很类似,两者区别是单例模式的关注点是创建单一对象,享元模式的关注点是规划创建对象。

享元模式不太好理解,它的难点在于理解它的结构以及为什么会创造出这样的设计结构。我从一本书上的享元模式的例子中理解了享元模式的目的以及实现。书中的例子是以“文档编辑器”加载数据为例:

通常上,文档编辑器上的文字或者字母,每个文字、字母都应该有一个存储

在这里插入图片描述

但是在物理结构上,却是相同的文字、字母共享同一个flyweight对象,从一个池中取数据,这种加载模式就是享元模式。

在这里插入图片描述

二、优点

(1)减少对象的创建,降低系统的内存,使效率提高。

三、缺点

网上都说下面的是缺点,我并不这样认为,这是享元模式的特点。除了创建对象需要工厂外,内部外部状态也是其特点之一。
(1)享元模式需要区分出内部状态和外部状态,内部状态不可查看,外部状态是对象方法执行的参数,是客户赋予对象的,是可见的。外部状态在不同内部状态的对象下的方法中执行,可能产生不同的结果。

四、使用场景

(1)一个应用程序使用了大量的对象
(2)完全由于使用大量的对象,造成很大的存储开销
(3)对象的大多数状态都可变为外部状态
(4)如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象
(5)应用程序不依赖于对象标识,由于Flyweight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

五、示例

模拟文档编辑器,写了一个简单的文字加载程序。如下:

1.抽象享元类

定义加载字体的抽象方法

public abstract class Flyweight {

    /**
     * 加载字体
     *
     * @param fontAttribute
     */
    abstract String load(FontAttribute fontAttribute);
}

2.文字属性类

定义文字的属性

@Data
public class FontAttribute {
    /**
     * 字体颜色:30黑 31红 32绿 33黄 34蓝 35紫 36深绿 37白
     */
    private Integer color;
    /**
     * 字体格式:0重置 1加粗 2减弱 3斜体 4下划线 5慢速闪烁 6快速闪烁
     */
    private Integer fontType;
}

3.具体文字类

定义加载字体的实现方法,以及文字标志量

public class Font extends Flyweight {
	//文字为内在属性
    private String word;

    public Font(String word) {
        this.word = word;
    }

    /**
     * 加载字体,FontAttribute为外在属性
     *
     * @param fontAttribute
     */
    @Override
    public String load(FontAttribute fontAttribute) {
    	//格式化字体属性
        return String.format("\033[%d;%dm%s\033[0m",fontAttribute.getColor(),fontAttribute.getFontType(),this.word);
    }
}

4.文字工厂类

定义创建文字的方法

public class FontFactory {
    HashMap<String, Font> fontHashMap = new HashMap<>();

    /**
     * 造字
     *
     * @param word
     * @return
     */
    public Font createFont(String word) {
    	//如果map中有该文字,则直接获取,不需要创建
        if (fontHashMap.containsKey(word)) {
            return fontHashMap.get(word);
        }
        //若map中不存在该文字,则造字
        return new Font(word);
    }
}

5.Client

定义调用方法

public class Client {
    public static void main(String[] args) {
        FontFactory factory = new FontFactory();
        //文字
        String[] words = {"h", "e", "l", "l", "o", "w", "o", "r", "l", "d"};
        //颜色编码
        Integer[] colors = {30, 31, 32, 33, 34, 35, 36, 37};
        //字体格式
        Integer[] fontTypes = {0, 1, 2, 3, 4, 5, 6, 7};

        for (int i = 0; i < words.length; i++) {
            Font font = factory.createFont(words[i]);
            FontAttribute attribute = new FontAttribute();
            //设置字体属性
            attribute.setColor(colors[i % colors.length]);
            attribute.setFontType(fontTypes[i % fontTypes.length]);
            //打印文字
            System.out.print(font.load(attribute));
        }
    }
}

效果:

在这里插入图片描述
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门