Java版设计模式之【享元模式】

222 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

概述

享元模式,是结构型设计模式的一种,主要用于减少创建对象的数量,是池技术的重要实现方式,可以降低大量重复的、细粒度的类在内存中的开销,以减少内存占用和提高性能。

角色

抽象享元:类中包含原始对象中部分能在多个对象中共享的状态,享元中存储的状态被称为“内在状态”,外部通过参数型数传入的称为“外在状态”。

具体享元:实现抽象享元定义的业务,其内部状态必须与环境无关,使其可以在系统内共享。

享元工厂:主要用来构造一个容器池,负责创建和管理享元对象,提供获取享元对象的方法,保证其可以适当的被系统共享。客户端发起请求后,它会先检查池中是否有符合要求的对象,如果有则返回该对象,如果没有就根据参数创建新的享元对象。

客户端:负责计算或存储享元的外在状态,对于客户端来说,享元是一种可以在运行时进行配置的模板对象。

模板

抽象享元:定义了图形所需实现的功能。

/**
 * 图形接口
 */
public interface Shape {
    /**
     * 绘制图形
     */
    void draw();
}

具体享元:实现了图形接口的绘制功能,同时定义了若干内在状态与外在状态。

/**
 * 圆形
 */
public class Circle implements Shape {

    /**
     * 颜色
     */
    private String color;
    /**
     * X坐标
     */
    private int x;
    /**
     * Y坐标
     */
    private int y;
    /**
     * 半径
     */
    private int radius;

    @Override
    public void draw() {
        System.out.println("Circle: Draw() [Color : " + color
                + ", x : " + x + ", y :" + y + ", radius :" + 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;
    }
}

享元工厂:创建一个工厂,生成基于给定信息的实体类的对象,通过Map模拟容器池存储享元对象。

/**
 * 享元工厂
 */
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("---------------------------------------------------------------");
            System.out.println("Creating circle of color : " + color);
        }
        return circle;
    }
}

客户端:使用工厂类,通过传递颜色信息来获取实体类的对象。

public class FlyweightPatternDemo {
    /**
     * 颜色数组
     */
    private static final String[] colors = {"Red", "Green", "Blue", "White", "Black"};
    private static Random random = new Random();

    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[random.nextInt(colors.length)];
    }

    /**
     * 随机生成X坐标
     */
    private static int getRandomX() {
        return random.nextInt(100);
    }

    /**
     * 随机生成Y坐标
     */
    private static int getRandomY() {
        return random.nextInt(100);
    }
}

image.png

小结

优点

提高性能:大幅减少内存中对象的数量,降低程序对内存的占用。

缺点

复杂化:提高了系统的复杂度,需要分离出外部状态和内部状态,而且内部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

耗时变长:每次调用都需要读取外部状态,进行重新计算,变相延长程序运行耗时。

适用场景

  • 系统中有大量相似的对象,且这些对象耗费大量内存。
  • 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关。
  • 需要缓冲池的场景。

最后

文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!!!

如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!