设计模式之享元模式

写在前面

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

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)

相关推荐
evans在进步17 小时前
Java 常用设计模式入门:建造者、工厂、单例、外观与代理
java·python·设计模式
字节跳动开源1 天前
VisActor全新图可视化开源项目:VGraph
前端·设计模式·开源
码匠许师傅1 天前
【设计模式精讲】11.桥接模式(Bridge)
c++·设计模式·桥接模式·uml
学习星球2 天前
AI Agent 成本工程实战:从 OpenAI Codex 的 8 个“烧 Token“Bug 学起
人工智能·设计模式·微信小程序
AI人工智能+电脑小能手2 天前
大白话说Java设计模式-46-责任链模式(业务实战篇)
java·设计模式·责任链模式·风控校验·servlet filter·spring interceptor·链式处理
码匠许师傅3 天前
【设计模式精讲】7.建造者模式(Builder)
设计模式·建造者模式
码匠许师傅3 天前
【设计模式精讲】6.抽象工厂(Abstract Factory)
c++·设计模式
workflower4 天前
人形机器人灵巧手产业链
人工智能·设计模式·机器人·云计算·无人机
Java后端的Ai之路4 天前
03、Python - 抽象工厂模式
开发语言·python·设计模式·抽象工厂模式·通用智慧
AI人工智能+电脑小能手4 天前
大白话说Java设计模式-45-解释器模式(源码剖析篇)
java·设计模式·解释器模式·源码分析·pattern·spel·javacc