zoukankan      html  css  js  c++  java
  • 享元模式(Flyweight Pattern)

    定义:

         采用一个共享来避免大量拥有相同内容对象的开销。这种开销中最常见、直观的就是内存的损耗。享元模式以共享的方式高效的支持大量的细粒度对象。

         享元的英文是flyweight,是一个来自体育方面的专业用语,在拳击、摔跤和举重比赛中特指最轻量的级别。把这个单词移植到软件工程中,也是用来表示特别小的对象,即细粒度的对象。至于为什么把flyweight翻译为享元,可以理解为共享元对象,也就是共享细粒度对象。

          享元模式中区分了内蕴状态和外蕴状态。内蕴状态不能改变,是可以共享的。外蕴状态是可以的改变的,不能共享,由客户端保持。

    模式组成:

    • Flyweight: 抽象享元类。所有具体享元类的超类或者接口,通过这个接口,Flyweight可以接受并作用于外部专题
    • ConcreteFlyweight: 具体享元类。指定内部状态,为内部状态增加存储空间
    • FlyweightFactory: 享元工厂类。用来创建并管理Flyweight对象,它主要用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory就会提供一个已经创建的Flyweight对象或者新建一个(如果不存在)。


    uml类图:



     

    模式分类:

    • 单纯享元模式(即该对象没有外蕴状态,整个对象可以共享,类似于单例模式)
    • 复合享元模式(该对象有内蕴状态,也有外蕴状态,内蕴状态共享)

     

    优点:

    • 极大的减少系统中对象的个数,节省内存的开销
    • 避免创建过多的对象,提升性能

     

    缺点:(这也算缺点?有待考究)

    • 由于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了
    • 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长


    应用场景:

    • 存在大量重复对象的场景

    在Java中,lang包下的Integer类,对于经常使用的-128 到 127 范围内的Integer对象当类一被加载时就被创建了,并保存在cache数组中,一旦程序调用valueOf 方法,如果i的值是在-128 到 127 之间就直接在cache缓存数组中去取Integer对象而不是创建一个新对象,这就是享元模式的应用。

     

        • java.lang.Integer#valueOf(int)
        • java.lang.Boolean#valueOf(boolean)
        • java.lang.Byte#valueOf(byte)
        • java.lang.Character#valueOf(char)

     


    举个栗子:

     

    定义抽象享元角色

    abstract class Dish {
        public abstract void desc();
    }

     

    定义具体享元角色

    class ButterMoshroom extends Dish {
        public String taste;
    
        public ButterMoshroom(String taste) {
            this.taste = taste;
        }
    
        @Override
        public void desc() {
            System.out.println(taste + "酱野山菌");
        }
    }

    定义工厂

    class ButterMoshroomFactory {
        static Map<String, Dish> dishes = new HashMap<String, Dish>();
    
        public synchronized static Dish getDish(String taste) {
            Dish dish = dishes.get(taste);
            if (dish == null) {
                dish = new ButterMoshroom(taste);
            }
            dishes.put(taste, dish);
            return dish;
        }
    }

    客户端调用

    public static void main(String[] args) {
            ButterMoshroomFactory.getDish("xo").desc();
            ButterMoshroomFactory.getDish("番茄").desc();
        }

    输出

     

  • 相关阅读:
    作为前端开发兼任产品专员是一种咋样的体验
    css忽略某一层的存在:pointer-events:none
    响应式网站对百度友好关键
    移动站点对百度友好全解
    如何布局您的PC站和移动站,并表达两者之间内容的对应关系
    猫眼电影App抓包获取评论数据接口
    字符串模拟大数相加——Java实现
    计算机网络知识小结
    二叉树与双向链表问题
    算法编程题积累(4)——腾讯笔试"有趣的数字“问题
  • 原文地址:https://www.cnblogs.com/amei0/p/7930013.html
Copyright © 2011-2022 走看看