能省一点是一点 - 享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)

  • [享元模式(Flyweight Pattern)](#享元模式(Flyweight Pattern))

享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)是一种结构型设计模式,它主要用于减少创建大量细粒度对象所带来的内存占用问题。通过共享尽可能多的对象,即所谓的"享元",来减少内存使用量和提高性能。这种设计模式特别适合于需要大量创建相同对象的情况。而且不要被享元这个名称迷惑,Flyweight的意思是轻量级的意思,更多的意思,这个模式是想告诉共享内存对象这个意思。

为什么会有这种设计模式

比如,当我们要构建的系统中有大量基本一样的元素的时候。

小时候我们玩过的像素风的游戏,大家可以看到实际上里面的各种场景就是有大量的基础元素拼装出来的。有很多完全一样的像素块,那对这些像素块,我们不需要每次用的时候都创建新的像素块对象。因为新建新的对象,需要消耗堆内存,而且这种消耗是没有意义的。

享元模式(Flyweight Pattern)概述

当一个软件需要创建大量的对象的时候,就会导致内存消耗过多,系统性能下降。而享元模式就是为了解决这个问题而出现的设计模式。

享元模式(Flyweight Pattern)的核心思想: 如果一个对象实例创建之后不可变的话,反复创建这种实例就变得没有必要,直接向客户端返回一个共享的实例就可以了,这样既节省了内存,还避免了创建对象的过程,提升运行效率。

享元模式包含的角色:

享元模式主要包含以下四种角色

  • 抽象享元(Flyweight)角色:是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
  • 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
  • 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
  • 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

享元模式应用场景

应用场景其实是围绕着享元模式的核心设计思想,减少对象的创建展开的。大致有下面几种:

  1. 软件设计中有大量相似的对象
  2. 缓存场景
  3. 需要多次重复使用某一个对象的时候

talk is cheap, show you my code

我们设计围棋的时候,会发现,白棋和黑棋会有很多,但是它们都是一样的。所以我们通过利用享元模式来设计创建围棋中的棋子。

围棋棋子 Go chess pieces

java 复制代码
public class GoChessPiecesFactory {
    public static Map<String, AbstractGoChessPieces> map = new HashMap<>();

    public static AbstractGoChessPieces getAbstractGoChessPieces(String color) {
        if (map.containsKey(color)) {
            return map.get(color);
        }else {
            if (color.equals("black")) {
                AbstractGoChessPieces black = new BlackGoChessPieces();
                map.put("black", black);
            }
            if (color.equals("white")) {
                AbstractGoChessPieces white = new WhiteGoChessPieces();
                map.put("white", white);
            }
        }
        return map.getOrDefault(color, null);
    }
}
java 复制代码
abstract class  AbstractGoChessPieces {
    String color;

    public abstract void display();

}

class BlackGoChessPieces extends AbstractGoChessPieces {

    @Override
    public void display() {
        System.out.println("black");
    }
}

class WhiteGoChessPieces extends AbstractGoChessPieces {

    @Override
    public void display() {
        System.out.println("white");
    }
}

public class Test4 {
    public static void main(String[] args) {
        AbstractGoChessPieces black = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces black1 = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces black2 = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces white = GoChessPiecesFactory.getAbstractGoChessPieces("white");
        AbstractGoChessPieces white1 = GoChessPiecesFactory.getAbstractGoChessPieces("white");
        System.out.println(black == black1);
        System.out.println(black1 == black2);
        System.out.println(white == white1);

        black.display();
        white.display();
    }

}

输出结果

java 复制代码
true
true
true
black
white

代码解释:

  1. AbstractGoChessPieces 抽象类 : 定义了一个抽象类 AbstractGoChessPieces,表示围棋棋子的基本属性和行为。
  2. BlackGoChessPieces 类 :继承自 AbstractGoChessPieces,表示黑色棋子。
  3. WhiteGoChessPieces 类 : 继承自 AbstractGoChessPieces,表示白色棋子。
  4. GoChessPiecesFactory 类 :工厂类 GoChessPiecesFactory 负责创建并缓存 AbstractGoChessPieces 的实例。

总结

当代码实现中出现大量相同对象的时候,我们就可以考虑使用享元模式。这种设计模式通过共享对象,节约了内存空间,提升了系统性能。

优点:

  1. 减少内存中的对象数量
  2. 享元模式外部状态不影响内部状态
    缺点:
  3. 享元模式需要隔离出内外两种状态,会使得代码逻辑变得复杂一点
相关推荐
桂月二二2 小时前
Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署
java·docker·kubernetes
liuxin334455662 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
ke_wu2 小时前
结构型设计模式
开发语言·设计模式·组合模式·简单工厂模式·工厂方法模式·抽象工厂模式·装饰器模式
小马爱打代码2 小时前
设计模式详解(建造者模式)
java·设计模式·建造者模式
小王爱吃月亮糖2 小时前
C++的23种设计模式
开发语言·c++·qt·算法·设计模式·ecmascript
栗子~~3 小时前
idea 8年使用整理
java·ide·intellij-idea
2301_801483693 小时前
Maven核心概念
java·maven
_im.m.z3 小时前
【设计模式学习笔记】1. 设计模式概述
笔记·学习·设计模式
Q_19284999063 小时前
基于Spring Boot的电影售票系统
java·spring boot·后端
我要学编程(ಥ_ಥ)4 小时前
初始JavaEE篇 —— 网络原理---传输层协议:深入理解UDP/TCP
java·网络·tcp/ip·udp·java-ee