设计模式之享元模式

写在前面

本文看下一种结构型设计模式,享元模式。

1:介绍

1.1:什么时候使用享元模式

当程序需要大量的重复对象,并且这些大量的重复对象只有部分属性不相同,其他都是相同的时候,就可以考虑使用享元设计模式设计模式来实现。典型的如围棋游戏中的棋子,除了颜色和位置不同外,其他都相同。射击游戏中的子弹,除了大小,型号,杀伤力等不同外,其他都相同。

1.2:UML类图

享元设计模式,包含如下元素:

复制代码
1:Flyweight
    定义享元对象的公共操作
2:ConcreteFlyweight
    具体的享元对象
3:FlyweightFactory
    享元对象工厂,负责生产享元对象,方便客户端获取享元对象的同时,也可以缓存享元对象,防止因为创建过多的对象而导致内存溢出等问题(想一下射击游戏,用户如果是用机关枪一直突突突,得创建多少对象啊)

UML图如下:

另外,享元设计模式分为内部状态和外部状态,如围棋游戏,棋子的黑色和白色,就是内部状态,在对象的内部定义和维护,是可以共享的,但是落子的位置则是各不相同的,就是外部状态,需要外部传入。如果是工作中认为场景适合使用享元设计模式则一定要考虑清楚内部状态和外部状态的问题。

2:实例

源码

2.1:场景

围棋游戏,创建游戏中的黑子和白子。

2.2:程序

  • 享元接口
java 复制代码
public interface Chess {
    // 绘制棋子(落子,走一步棋)
    // 位置,外部状态,由外部传入
    void draw(int x,int y);
}
  • 内部状态枚举
java 复制代码
public enum Color {
    BLACK("黑色"), WHITE("白色");
    private String name;

    // 默认就是private的,并且不能反射,暴力也不行
    Color(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAlias() {
        return this.name;
    }
}
  • 具体享元类
    黑子和白子类:
java 复制代码
//黑棋
public class BlackChess implements Chess {
    // 内部状态,共享
    private final Color color = Color.BLACK;

    private final String sharp = "圆形";

    public Color getColor() {
        return color;
    }

    // 外部状态
    @Override
    public void draw(int x, int y) {
        System.out.println(String.format("%s%s棋子置于(%d,%d)处", sharp, color.getAlias(), x, y));
    }
}

//白棋
public class WhiteChess implements Chess {
    //内部状态,共享
    private final Color color = Color.WHITE;

    private final String sharp = "圆形";

    public Color getColor() {
        return color;
    }

    @Override
    public void draw(int x, int y) {
        System.out.println(String.format("%s%s棋子置于(%d,%d)处", sharp, color.getAlias(), x, y));
    }
}
  • 享元工厂类
java 复制代码
public class ChessFactory {
    private static final Map<Color, Chess> chessMap = new HashMap<>();

    public static Chess getChess(Color color) {
        Chess chess = chessMap.get(color);
        if (chess == null) {
            chess = color == Color.WHITE ? new WhiteChess() : new BlackChess();
            chessMap.put(color, chess);
        }
        return chess;
    }
}
  • 测试
java 复制代码
public class FlyweightClient {

    @Test
    public void playChess() {
        //下黑子
        Chess backChess1 = ChessFactory.getChess(Color.BLACK);
        backChess1.draw(2, 5);

        //下白子
        Chess whiteChess = ChessFactory.getChess(Color.WHITE);
        whiteChess.draw(3, 5);

        //下黑子
        Chess backChess2 = ChessFactory.getChess(Color.BLACK);
        backChess2.draw(2, 6);

        System.out.println(String.format("backChess1:%d | backChess2:%d | whiteChess:%d",
                backChess1.hashCode(), backChess2.hashCode(), whiteChess.hashCode()));
    }
}

运行:

复制代码
圆形黑色棋子置于(2,5)处
圆形白色棋子置于(3,5)处
圆形黑色棋子置于(2,6)处
backChess1:1327763628 | backChess2:1327763628 | whiteChess:1915503092

Process finished with exit code 0

写在后面

参考文章列表

秒懂设计模式之享元模式(Flyweight Pattern)

相关推荐
vker2 小时前
第 1 天:单例模式(Singleton Pattern)—— 创建型模式
java·设计模式
晨米酱21 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤1 天前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机2 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript