23种常用设计模式-享元(Flyweight)模式

305次阅读
没有评论

共计 2389 个字符,预计需要花费 6 分钟才能阅读完成。

内容目录

享元模式

概述

 享元(Flyweight)模式:运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此又称为轻量级模式。

 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能。它提供了减少对象数量从而改善应用所需的对象结构的方式。

我们可以将享元模式与单例模式放在一起谈论,通俗点来讲,单例模式是维护一个对象的重复使用,而享元模式维护的是多个对象的重复使用。

类型

 享元模式属于结构性模式。

介绍

  • 目的:运用共享技术有效地支持大量细粒度的对象。
  • 主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中重复使用的对象抽离出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
  • 如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识所标识的对象。

示例代码

 假设一个程序需要随机绘制10个圆形,而这些圆形的颜色仅有四种:red、blue、white、black,半径是随机的。

图形操作接口

package flyweight;

public interface IShape {
    void draw();
}

圆的实现

package flyweight;

public class Circle implements IShape{

    private double radius;
    private String color;

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

    @Override
    public void draw() {
        System.out.println("绘制了一个半径为:" + radius + ",颜色为:" + color + "的圆.");
    }
}

享元类

 该类用于管理多个会重复使用的圆实例。

package flyweight;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class FlyweightFactory {
    private static final Map<String,IShape> circleMap = new ConcurrentHashMap<String,IShape>();

    public static IShape getCircle(String color){
        IShape circle = circleMap.get(color);
        if ( circle == null){
            circle = new Circle(color);
            circleMap.put(color,circle);
            System.out.println("创建了一个颜色为" + color + "的圆。");
        }
        return circle;
    }
}

 测试代码及运行结果如下:

package flyweight;

import org.junit.Test;

/**
 * ClassName: FlyweightTest <br/>
 *
 * @author Ning <br/>
 * @date 2023/10/21 0021
 * @since JDK 11
 */
public class FlyweightTest {
    private static final String colors[] = {"red","blue","white","black"};
    @Test
    public void flyweightTest(){

        for (int i = 0; i < 10; i++) {
            Circle circle = (Circle) FlyweightFactory.getCircle(getColor());
            circle.setRadius(getRadius());
            circle.draw();
        }
    }

    public String getColor(){
        return colors[(int) (Math.random() * colors.length)];
    }
    public double getRadius(){
        return Math.random() * 100;
    }
}
创建了一个颜色为white的圆。
绘制了一个半径为:66.00547720180391,颜色为:white的圆.
创建了一个颜色为red的圆。
绘制了一个半径为:37.62220674526002,颜色为:red的圆.
绘制了一个半径为:66.55351032418484,颜色为:white的圆.
创建了一个颜色为black的圆。
绘制了一个半径为:34.16085784102466,颜色为:black的圆.
绘制了一个半径为:96.79539622581301,颜色为:white的圆.
绘制了一个半径为:11.015661092424168,颜色为:black的圆.
绘制了一个半径为:99.54145083907062,颜色为:red的圆.
创建了一个颜色为blue的圆。
绘制了一个半径为:70.0762962719384,颜色为:blue的圆.
绘制了一个半径为:73.8598169398206,颜色为:red的圆.
绘制了一个半径为:65.00896272569092,颜色为:white的圆.

 享元模式的核心代码就是通过map来存储具有唯一标识和需要重复使用的对象。具体实现可参考上述的FlyweightFactory.

其它

 有个细节值得注意:有些对象本身不一样,但通过一点点变化后就可以复用,我们编程时可能稍不注意就会忘记复用这些对象。比如说伟大的超级玛丽,谁能想到草和云更改一下颜色就可以实现复用呢?还有里面的三种乌龟,换一个颜色、加一个装饰就变成了不同的怪。

 在超级玛丽中,这样的细节还有很多,正是这些精湛的复用使得这一款红遍全球的游戏仅有 40KB 大小。正是印证了那句名言:神在细节之中。

正文完
 
PG Thinker
版权声明:本站原创文章,由 PG Thinker 2023-10-22发表,共计2389字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
热评文章
Rust中所有权与借用规则概述

Rust中所有权与借用规则概述

在GC与手动管理内存之间,Rust选择了第三种:所有权机制...