学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • 设计模式

    • 设计模式-工厂模式
    • 设计模式-抽象工厂模式
    • 设计模式-单例模式
    • 设计模式-建造者模式
    • 设计模式-原型模式
    • 设计模式-适配器模式
    • 设计模式-桥接模式
    • 设计模式-组合模式
    • 设计模式-外观模式
    • 设计模式-装饰模式
    • 设计模式-享元模式
      • 设计模式-享元模式
        • 概述
        • 定义
      • 享元模式结构
      • 享元模式应用案例
      • 享元模式优缺点
      • 享元模式使用环境
      • 享元模式在Java中的运用
        • Integer
        • String
      • 参考
    • 设计模式-代理模式
    • 设计模式-职责链模式
    • 设计模式-命令模式
    • 设计模式-迭代器模式
    • 设计模式-中介者模式
    • 设计模式-观察者模式
    • 设计模式-状态模式
    • 设计模式-策略模式
  • 算法思想

  • 编码规范

  • 技术思想
  • 设计模式
旭日
2023-03-27
目录

设计模式-享元模式

# 设计模式-享元模式

# 概述

如果一个软件系统在运行时所创建的相同或相似对象数量太多,将导致运行代价过高,带来系统资源浪费、性能下降等问题。

例如在一个文本字符串中存在很多重复的字符,如果每一个字符都用一个单独的对象来表示,将会占用较多的内存空间,那么如何避免系统中出现大量相同或相似的对象。

# 定义

当系统中存在大量相同或者相似的对象时,享元模式通过共享技术实现相同或相似的细粒度对象的复用,从而节约了内存空间、提高了系统性能。

享元模式: 运用共享技术有效地支持大量细粒度对象的复用。

# 享元模式结构

享元模式包含以下4个角色:

  1. UnsharedConcreteFlyweight 是非享元角色,里面包含了非共享的外部状态信息 info;

  2. Flyweight 是抽象享元角色,里面包含了享元方法 operation(UnsharedConcreteFlyweight state),非享元的外部状态以参数的形式通过该方法传入;

  3. ConcreteFlyweight 是具体享元角色,包含了关键字 key,它实现了抽象享元接口;

  4. FlyweightFactory 是享元工厂角色,它通过关键字 key 来管理具体享元;

image-20220507200124850

# 享元模式应用案例

我们来实现一个圆形工厂,对于相同颜色的圆形我们就只创建一次,后续颜色相同的圆形直接使用之前创建的。

1、创建一个图形接口

public interface Shape {
    void draw();
}

2、创建圆形

public class Circle implements Shape{
    private final String color;
    private int x;
    private int y;
    private int radius;

    public Circle(String color) {
        this.color = color;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Circle: Draw() [Color : " + color
                + ", x : " + x + ", y :" + y + ", radius :" + radius);
    }
}

3、创建圆形工厂

public class ShapeFactory {
    private static final HashMap<String, Shape> circleMap = new HashMap<>();

    public static Shape getCircle(String color) {
        Circle circle = (Circle) circleMap.get(color);

        if (circle == null) {
            circle = new Circle(color);
            circleMap.put(color, circle);
            System.out.println("Creating circle of color : " + color);
        }
        return circle;
    }
}

4、案例实现

public class FlyweightPatternDemo {
    private static final String[] colors = {"Red", "Green", "Blue", "White", "Black"};

    public static void main(String[] args) {
        for (int i = 0; i < 20; ++i) {
            Circle circle = (Circle) ShapeFactory.getCircle(getRandomColor());
            circle.setX(getRandomX());
            circle.setY(getRandomY());
            circle.setRadius(100);
            circle.draw();
        }
    }

    private static String getRandomColor() {
        return colors[(int) (Math.random() * colors.length)];
    }

    private static int getRandomX() {
        return (int) (Math.random() * 100);
    }

    private static int getRandomY() {
        return (int) (Math.random() * 100);
    }
}

// 输出
Creating circle of color : Black
Circle: Draw() [Color : Black, x : 23, y :60, radius :100
Circle: Draw() [Color : Black, x : 97, y :50, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 52, y :25, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 46, y :90, radius :100
Circle: Draw() [Color : Green, x : 25, y :23, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 91, y :33, radius :100
Circle: Draw() [Color : Black, x : 2, y :73, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 56, y :60, radius :100
Circle: Draw() [Color : Red, x : 21, y :86, radius :100
Circle: Draw() [Color : White, x : 70, y :62, radius :100
Circle: Draw() [Color : Red, x : 47, y :64, radius :100
Circle: Draw() [Color : Green, x : 24, y :76, radius :100
Circle: Draw() [Color : Black, x : 95, y :8, radius :100
Circle: Draw() [Color : White, x : 35, y :88, radius :100
Circle: Draw() [Color : Green, x : 94, y :63, radius :100
Circle: Draw() [Color : Red, x : 12, y :1, radius :100
Circle: Draw() [Color : White, x : 36, y :2, radius :100
Circle: Draw() [Color : Red, x : 34, y :35, radius :100
Circle: Draw() [Color : Blue, x : 64, y :52, radius :100
Circle: Draw() [Color : Red, x : 54, y :14, radius :100

# 享元模式优缺点

优点:

  1. 享元模式可以减少内存中对象的数量,使得相同或者相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
  2. 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使享元对象可以在不同环境中被共享。

缺点:

  1. 享元模式使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
  2. 为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使运行时间变长。

# 享元模式使用环境

  1. 一个系统中有大量相同或者相似的对象,造成内存的大量耗费。
  2. 对象的大部分状态可以外部化,可以将这些外部状态传入对象中。
  3. 在使用享元模式需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此应当在需要多次重复使用享元对象时才使用享元对象。

# 享元模式在Java中的运用

# Integer

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }
public class FlyweightPatternJavaInteger {
    public static void main(String[] args) {
        Integer x = Integer.valueOf(127);
        Integer y = Integer.valueOf(127);
        Integer z = new Integer(127);
        System.out.println(x == y);
        System.out.println(x == z);

        Integer m = Integer.valueOf(200);
        Integer n = Integer.valueOf(200);
        System.out.println(m == n);
    }
}

// 输出
true
false
false

小结:

1、在valueOf 方法中,先判断值是否在 IntegerCache 中,如果不在,就创建新的Integer(new), 否则,就直接从缓存池返回

2、IntegerCache范围在[-128, 127]之间。

3、如果超出这个范围,valueOf方法就会产生一个新的对象。

# String

public class FlyweightPatternJavaString {
    public static void main(String[] args) {
        String s1 = "wxx";
        String s2 = "wxx";
        String s3 = new String("wxx");
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
    }
}

// 输出
true
false
private final char value[];

# 参考

设计模式入门实践 (opens new window)

Java设计模式

#设计模式
上次更新: 2024/06/29, 15:13:44
设计模式-装饰模式
设计模式-代理模式

← 设计模式-装饰模式 设计模式-代理模式→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式