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();
        }

    输出

     

  • 相关阅读:
    2019/10/21 动手动脑
    2019/10/21 课堂测试---向数据库添加新用户
    2019/10/14 如何在静态方法中访问类的实例成员
    2019/10/14 构造函数、默认值、初始化块的优先级。
    2019/10/14 动手动脑---
    2019/9/30 极限测试(1)
    读《程序员的修炼之道------从小工到专家》有感 1
    课堂测试,统计小说<飘>前N个最常出现的单词
    Java课堂 动手动脑
    2019/9/23 课堂测试一 回文
  • 原文地址:https://www.cnblogs.com/amei0/p/7930013.html
Copyright © 2011-2022 走看看