zoukankan      html  css  js  c++  java
  • 设计模式之享元模式

    设计模式之享元模式

    1.享元模式定义:是池技术重要的实现方式。使用共享对象可有效地支持大量细粒度的对象

    目的:主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

    享元模式为我们提出了两个要求:1.细粒度的对象 2.共享对象

    对象的内部状态和外部状态:

    内部状态:内部状态指的是对象中可以共享出来的信息。存贮在享元对象对象内部并且不会随对象内部改变而改变的对象。不必直接存储在具体的对象中,属于可以共享的部分

    外部状态:外部对象是对象得以依赖的一个标记,是随环境的改变而改变。不可共享的状态,是一批对象的统一标识,是唯一的索引值

    2.享元模式通用的类图:

     

    类图说明:

    FlyWeight:抽象享元角色

    简单来说就是一个产品的抽象类,同时定义出对象的外部接口和内部状态的接口和实现

    ConcreteFlyweight :具体享元角色

    具体的一个角色,实现享元角色定义的业务。该角色需要注意的是内部状态处理与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是绝对不允许的。

    UnsharedConcreteFlyweight: 不可共享的享元角色

    FlyweightFactory享元工厂:指责非常简单,是就是构造一个池容器。同时提供从池中获取对象的方法

    3.享元模式通用代码

     抽象享元角色:在抽象角色中,一般需要把外部状态和内部状态定义出来,避免子类随意扩展

    public abstract class Flyweight {
        // 内部状态
        private String intrinsic;
        // 外部状态 定义为final,防止无意修改了一下,造成池中混乱.在程序中,确认只需要一次赋值的属性,就设置为final.避免无意修改导致逻辑混乱,特别是session级别的常亮或者变量
        protected final String Extrinsic;
    
        // 要求享元角色必须接受外部状态
        public Flyweight(String extrinsic) {
            Extrinsic = extrinsic;
        }
    
        // 定义业务操作
        public abstract void operate();
        // 内部状态set/getter
    
        public String getIntrinsic() {
            return intrinsic;
        }
    
        public void setIntrinsic(String intrinsic) {
            this.intrinsic = intrinsic;
        }
    }
    

      

     具体享元角色

    public class ConcreteFlyWeight extends Flyweight {
        // 接受外部状态
        public ConcreteFlyWeight(String extrinsic) {
            super(extrinsic);
        }
    
        // 根据外部状态,进行逻辑操作
        @Override
        public void operate() {
            System.out.println("执行操作=========>" + this.Extrinsic);
        }
    }
    

      

    享元工厂

    public class FlyWeightFactory {
    
        // 定义一个池对象
        private static HashMap<String, Flyweight> pool = new HashMap<>();
    
        // 享元工厂
        public static Flyweight getFlyWeight(String extrinsic) {
            // 需要返回的对象
            Flyweight flyweight = null;
    
            if (pool.containsKey(extrinsic)) {
                flyweight = pool.get(extrinsic);
                System.out.println("直接从池中 取出数据==============>" + extrinsic);
            } else {
                // 根据外部状态撞见享元对象
                flyweight = new ConcreteFlyWeight(extrinsic);
                // 放置到池中
                pool.put(extrinsic, flyweight);
                System.out.println("池子中不存在数据,先创建,在放入池子中=============》" + extrinsic);
            }
            return flyweight;
        }
    }
    

      

    测试结果:

    public class TestFlyWeight {
    
        @Test
        public void test001() {
            Flyweight flyweight1 = FlyWeightFactory.getFlyWeight("thread-1");
            flyweight1.operate();
            Flyweight flyweight2 = FlyWeightFactory.getFlyWeight("thread-2");
            flyweight2.operate();
            Flyweight flyweight3 = FlyWeightFactory.getFlyWeight("thread-3");
            flyweight3.operate();
            Flyweight flyweight4 = FlyWeightFactory.getFlyWeight("thread-1");
            flyweight4.operate();
        }
    }
    

    运行截图:

    外部状态最好用java的基本类型作为标志,如String,int等,可以大幅度提升效率

    4.享元模式的优缺点

      优点:大大减少了对象的创建,降低了程序内存的占用,提高程序的性能

      缺点:提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变

    5.享元模式的使用场景

      1.系统中存在大量的相似的对象

      2.需要缓冲池的场景

    6.注意事项:

      1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。

      2、这些类必须有一个工厂对象加以控制。

    7.应用实例:

      1.ResueExecutor对JDBC的statement对象进行了封装。当执行相同SQL语句的时候,直接从缓存中取出Statement对象进行复用,避免了频繁创建和销毁对象

      2.数据库连接池

      3.String.intern方法。如果String的对象池中有该类型的值,则直接返回对象池中的对象,如果没有则创建一个字符串保存在字符串缓存池里面

  • 相关阅读:
    scala中List、Array、ListBuffer、ArrayList、Set
    Spark Pipeline
    Spark MLlib
    minikube
    proxychains 安装
    网络性能测试
    Flexvolume
    kubectl 获取信息
    centos7 莫名重起的问题
    fio 测试磁盘
  • 原文地址:https://www.cnblogs.com/yingxiaocao/p/13514674.html
Copyright © 2011-2022 走看看