• 16_享元模式


    【享元模式】

    享元模式是池技术的重要实现方式。

    享元模式使用共享对象有效地支持大量细粒度的对象。

    享元模式两个要求:细粒度对象和共享对象。在平时写java程序过程中,分配太多的对象到应用程序中将有损程序的心梗,同事还容易造成内存溢出,避免的方式之一就是采用享元模式的共享技术。

    要求细粒度对象,那么不可避免的使得对象数量多,且性质相近,我们将这些对象信息分为两部分:内部状态(intrinsic)和 外部状态(exetrinsic)。

    * 内部状态

    内部状态是对象可共享出来的信息,存储在享元对象内部并且不会随环境改变而改变。它可以作为一个对象的动态附加信息,不必直接存储在摸个具体的对象中,属于共享的部分。

    * 外部状态

    外部状态时对象得以依赖的一个标记,是随着环境改变而改变的、不可共享的状态。它是一批对象的统一标识,是唯一的一个索引值,相当于Map的键值key。

    [ 目的 ]

    享元模式的目的在于使用共享技术,使得一些细粒度的对象可以共享,我们的设计应该多使用细粒度的对象,这样便于重用或重构。

    【分类】

    [ 单纯享元模式 ]

    在单纯享元模式中,所有享元对象都是可以共享的。

    由3部分组成:

    * Flyweight 抽象享元角色

    简单的说就是一个产品的抽象类或接口,以规定出所有具体享元角色需要实现的方法。

    * ConcreteFlyweight 具体享元角色

    具体的一个产品类,实现抽象享元角色定义的业务。

    * FlyweightFactory 享元工厂

    职责非常简单,即构造一个池容器,同时提供从池中获得对象的方法。当一个客户端调用一个享元对象的时候,享元工厂角色应该先从对象池中获取,有则直接;若对象池中没有,则新实例化一个,并在对象池中放入该新实例化的对象。

    [ 复合享元模式 ]

    复合享元模式是将一些单纯享元模式加以复合,形成复合享元对象。这样的复合享元对象本身无法共享,但是他们能分解成单纯享元对象,后者可以分享。

    * Flyweight 抽象享元角色

    简单的说就是一个产品的抽象类或接口,以规定出所有具体享元角色需要实现的方法。

    * ConcreteFlyweight 具体享元角色

    具体的一个产品类,实现抽象享元角色定义的业务。

    * ConcreteCompositeFlyweight 复合享元角色(不可共享的享元对象unsharedConcreteFlyweight)

    不存在外部状态或安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。也称为不可共享的享元对象。

    * FlyweightFactory 享元工厂

    职责非常简单,即构造一个池容器,同时提供从池中获得对象的方法。当一个客户端调用一个享元对象的时候,享元工厂角色应该先从对象池中获取,有则直接;若对象池中没有,则新实例化一个,并在对象池中放入该新实例化的对象。

    【单纯享元模式 例子】

    package com.Higgin.Flyweight;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 抽象享元角色 
     */
    interface Flyweight{
        public void opetation();
    }
    
    /**
     * 具体享元角色
     */
    class ConcreteFlyweight implements Flyweight{
        private String state=null;
        
        public ConcreteFlyweight(String state) {
            this.state=state;
        }
        
        @Override
        public void opetation() {
            System.out.println("do some operation!");
        }
    }
    
    /**
     * 享元对象的工厂类
     */
    class FlyweightFactory{
        //HashMap类型的对象池
        private static Map<String,Flyweight> map=new HashMap<>();
        /**
         * 得到一个Flyweight
         * 1.对象池中已有的,直接获取
         * 2.对象池中没有的,实例化一个,然后放入对象池中
         */
        public static Flyweight getFlyweight(String state){
            Flyweight flyweight=map.get(state);   //对象池中若有直接获取
            if(flyweight==null){   //为null,即对象池中没有
                System.out.println(state+" 不存在,需要实例化一个放入池中...");   //提示作用
                flyweight=new ConcreteFlyweight(state);  
                map.put(state, flyweight);
            }else{    //仅作为提示作用
                System.out.println(state+" 已存在,无需实例化,直接取出...");     //提示作用
            }
            return flyweight;
        }
        //得到对象池中的对象数量
        public static int getObjectNum(){  
            return map.size();
        }
    }
    /**
     * 测试  单纯享元模式 
     */
    public class TestFlyweight {
        public static void main(String[] args) {
            Flyweight f1=FlyweightFactory.getFlyweight("小明");
            Flyweight f2=FlyweightFactory.getFlyweight("小明");
            Flyweight f3=FlyweightFactory.getFlyweight("小梦");
            Flyweight f4=FlyweightFactory.getFlyweight("小杰");
            Flyweight f5=FlyweightFactory.getFlyweight("小新");
            Flyweight f6=FlyweightFactory.getFlyweight("小琴");
            Flyweight f7=FlyweightFactory.getFlyweight("小琴");
            System.out.println(f1==f2);
            System.out.println(f5==f6);
            System.out.println(f6==f7);
            System.out.println("创建的对象数量:"+FlyweightFactory.getObjectNum());
        }
    }

    【运行结果】

  • 相关阅读:
    选择排序
    迭代器使用过程中为什么抛出ConcurrentModificationException
    自定义实现的ArrayList以及自定义实现的Iterator迭代器
    单链表
    collections方法记录
    JDK1.9中关于集合的新方法
    请使用时间相关的API,计算一个人从出生到现在一共活了多少天?
    java中对象的向上转型和向下转型
    异常相关知识整理
    可变参数相关知识
  • 原文地址:https://www.cnblogs.com/HigginCui/p/6229957.html
Copyright © 2020-2023  润新知