设计模式十五--享元模式

设计模式

享元模式

享元模式又称为轻量级模式,它是一种对象结构型模式,因为享元模式要求能够共享的对象必须是细粒度对象。享元模式是对象池的一种实现,实质就是缓存共享对象,降低内存消耗。

最常见的例子就是五子棋,在五子棋中棋子分为黑白两种颜色,这就是内部状态,不可改变。而双方落子的位置是动态变化的,所以棋子的坐标就是外部状态。使用享元模式,只需要黑白两个对象,大大减少了内存的消耗。

抽象享元角色Gobang

package com.wangscaler.flyweight;

/**
 * @author wangscaler
 * @date 2021.06.29 18:12
 */
public abstract class Gobang {
    protected int x;
    protected int y;
    protected String chess;

    public Gobang(String chess) {
        this.chess = chess;
    }

    public abstract void point(int x, int y);

    public void printPoint() {
        System.out.println(this.chess + "(" + this.x + "," + this.y + ")");
    }

}
复制代码

具体享元角色Black,实现了point方法

package com.wangscaler.flyweight;

/**
 * @author wangscaler
 * @date 2021.06.29 18:12
 */
public class Black extends Gobang {

    public Black() {
        super("黑子");
    }

    @Override
    public void point(int x, int y) {
        this.x = x;
        this.y = y;
        printPoint();
    }
}
复制代码

具体享元角色White

package com.wangscaler.flyweight;

/**
 * @author wangscaler
 * @date 2021.06.29 18:12
 */
public class White extends Gobang {
    public White() {
        super("白子");
    }

    @Override
    public void point(int x, int y) {
        this.x = x;
        this.y = y;
        printPoint();
    }
}
复制代码

享元工厂角色GobangFactory,获取黑棋白棋,没有则初始化,有则直接提供

package com.wangscaler.flyweight;

import java.util.HashMap;

/**
 * @author wangscaler
 * @date 2021.06.29 18:12
 */
public class GobangFactory {
    private static GobangFactory gobangFactory = new GobangFactory();

    private final HashMap<String, Gobang> cache = new HashMap<String, Gobang>();

    private GobangFactory() {
    }

    public static GobangFactory getInstance() {
        return gobangFactory;
    }

    public Gobang getChessmanObject(String type) {
        if (!cache.containsKey(type)) {
            if (type.equals("B")) {
                cache.put(type, new Black());
            } else if (type.equals("W")) {
                cache.put(type, new White());
            } else {
                System.out.println("棋子类型不正确");
            }
        }
        return cache.get(type);
    }

    public void getCount() {
        System.out.println("当前hashmap的个数" + cache.size());
    }

}
复制代码

main

package com.wangscaler.flyweight;

import java.util.Random;

/**
 * @author wangscaler
 * @date 2021.06.29 18:12
 */
public class Flyweight {
    public static void main(String[] args) {
        GobangFactory gobangFactory = GobangFactory.getInstance();
        Random random = new Random();
        Gobang gobang = null;
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                gobang = gobangFactory.getChessmanObject("B");
            } else {
                gobang = gobangFactory.getChessmanObject("W");
            }
            if (gobang != null) {
                gobang.point(i, random.nextInt(15));
                gobangFactory.getCount();
            }
        }
    }
}
复制代码

源码中的享元模式

JAVA 中的 Integer,这个之前的文章Java易错点2已经写过了,就不再赘述。

总结

享元模式,顾名思义享就是共享,元就是对象,即共享对象的模式。

享元模式的角色:

  1. 抽象享元角色:是所有的具体享元类的基类即产品的抽象类,定义出对象的外部状态(不可共享的状态,可以改变)和内部状态(不会随着环境的变化而变化),非享元的外部状态以参数的形式通过方法传入。
  2. 具体享元角色:即具体的产品对象,实现抽象享元角色中所规定的接口。
  3. 非享元角色:是不可以共享的外部状态。一般不会出现在享元工厂中。
  4. 享元工厂角色:负责创建和管理享元角色。当客户请求一个享元对象时,享元工厂检査系统中是否已经存在符合要求的享元对象,如果不存在则创建一个;如果存在,则直接提供。

使用场景:

1、有很多对象,且对象的状态可以外部化。

2、用标识码标识对象(像五子棋中的W和B、Integer中的-127到128),如果内存中有,直接取出来,没有则初始化。

3、享元模式的本质是分离与共享 : 分离变与不变,并且共享不变。实现对象的复用

参考资料

猜你喜欢

转载自juejin.im/post/6979406730207690765