享元模式

1、享元模式的概念

享元模式,英文Flyweight Pattern,属于结构型模式。主要用来减少创建对象的数量,进而减少内存占用来提高系统性能。我们都知道,创建出来的对象基本都会存放在JVM的堆中,堆中存在着大量的对象,也是GC回收的主要区域,内存中对象过多会影响系统性能,而享元模式的根本目的就是减少对象的创建,在一定程度上可以提高系统的性能。

享元模式尝试重用现有的同类对象,如果没有的话,再创建,如果已经存在着这样的对象,直接用而不是创建。

2、享元模式的特点

  • 重用现有的同类对象,没有再创建,尽量减少创建对象,从而减少内存开销,提高系统的性能。

3、关于享元模式

  • 使用目的:共享已有的同类对象,减少对象创建,减小系统开销,提高系统性能。
  • 解决问题:当需要创建大量的对象时,很可能内存会溢出,这时候可以将类型相同的对象抽象出来,然后在业务需要该类型对象的时候,直接返回内存中已存在的该类型对象,而不用频繁的创建。
  • 使用时机
    • 当系统中有大量对象并且会占用大量内存的时候。
    • 对象的状态可以外部化。
    • 系统并不依赖对象的身份。
  • 保证享元:用代表唯一的标识码来标识对象,当内存中有的话,直接返回这个标识码对应的对象,而不用重新创建。
  • 享元关键:这些共享对象用HashMap来进行存储。

4、享元模式的优缺点

优点:

  • 减少大量对象的创建,减少了系统开销,从而提高了系统的性能。

缺点:

  • 一定程度上提高了系统的复杂度,需要分离外部状态和内部状态。

5、享元模式的使用场景

  • 系统中存在着大量的相似对象。
  • 需要用到缓冲池时。

注意: 需要严格划分外部状态和内部状态,否则可能会引起线程安全问题。 其次,这些类必须有一个工厂对象加以控制。

6、享元模式的实现

(1)创建Shape接口和实现类

public interface Shape {
    
    void draw();

}

/*
 * 接口的实现类
 */
public class Circle implements Shape {

    private int x;

    private int y;

    private String color;

    private int radius;

    // 构造方法
    public Circle(String color) {
        this.color = color;
    }

    public int getX() {
        return x;
    }

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

    public int getY() {
        return y;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getRadius() {
        return radius;
    }

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

    @Override
    public void draw() {
        System.out.println("以坐标(" + this.x + "," + this.y + ")为圆心,以"
                + this.radius + "为半径画圆,圆内填充" + this.color);
    }

}

(2)创建工厂类

需要创建一个工厂类,用来管理对象的生成和返回,如下:

public class ShapeFactory {

    private static final HashMap<String, Circle> circleMap = new HashMap<>();

    // 定义一个方法,用于返回Shape对象
    public static Shape getCircle(String color) {
        // 先从Map中查找
        Circle circle = circleMap.get(color);
        // 找不到的话,再创建
        if (circle == null) {
            circle = new Circle(color);
            // 存进map里
            circleMap.put(color, circle);
            System.out.println("创建一个" + color + "的圆!");
        }
        return circle;
    }

}

(3)测试

public class Test {

    // 定义一个全局Random类型对象
    private static Random random = new Random();

    // 定义一个数组
    private static final String[] colors = {"红色", "绿色", "黄色", "灰色" };

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            // 获取随机颜色
            String randomColor = getColor();
            Circle circle = (Circle) ShapeFactory.getCircle(randomColor);
            circle.setX(getXRandom());
            circle.setY(getYRandom());
            circle.setRadius(10);
            circle.draw();
        }
    }

    // 定义一个方法,随机返回一个50以内的int型X坐标
    private static int getXRandom() {
        return random.nextInt(51);
    }

    // 随机返回Y坐标
    private static int getYRandom() {
        return random.nextInt(51);
    }

    // 随机返回一个数组中的颜色
    private static String getColor() {
        // 数组转成List
        List<String> colors2 = Arrays.asList(colors);
        // 随机返回一个集合长度以内的整数
        int res = random.nextInt(colors2.size());
        return colors2.get(res);
    }

}

在这里插入图片描述
可以看到,类似的对象,确实只创建了一次,后来需要的时候,是直接从内存中取到的,而不是再重新创建。

7、小结

享元模式的目的在于减少相似对象的重复创建,从而减少系统开销来提高系统性能,当系统中存在大量的类似对象时,可以考虑采用享元模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值