深入浅出设计模式 - 享元模式

简介: 深入浅出设计模式 - 享元模式

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

1687871498384.jpg

1、什么是享元模式

享元模式是一种结构型设计模式,它通过共享对象来减少内存使用和提高性能。在享元模式中,如果多个对象需要共享相同的状态或数据,那么可以将这些状态或数据抽象出来,作为一个享元对象,由多个对象共享使用。这样可以减少对象的数量,节省内存空间,并且提高系统的性能。

享元模式中的关键是将对象的状态分为内部状态和外部状态。内部状态是可以被多个对象共享的状态,它通常是不变的,而外部状态是不可以被共享的状态,它会随着对象的不同而不同。

在实现享元模式时,通常会使用工厂类来创建享元对象,并且将已经创建的对象保存在一个池中,以便下次使用时直接从池中获取,避免重复创建对象。

享元模式可以用于需要大量相似对象的场景,例如图形编辑器中的图形对象,游戏中的角色对象等。

2、享元模式的优缺点

享元模式的优点:

  1. 减少内存消耗:通过共享对象,可以减少系统中对象的数量,从而减少内存消耗。

  2. 提高性能:由于共享对象可以避免重复创建对象,因此可以提高系统的性能。

  3. 可以实现对象的复用:通过共享对象,可以实现对象的复用,避免重复创建对象。

  4. 可以实现对象的可共享性:通过将对象的状态分为内部状态和外部状态,可以实现对象的可共享性。

享元模式的缺点:

  1. 实现较为复杂:由于享元模式需要将对象的状态分为内部状态和外部状态,并且需要使用工厂类来管理共享对象,因此实现较为复杂。

  2. 可能会影响系统的维护性:由于享元模式将对象的状态分为内部状态和外部状态,因此可能会影响系统的维护性,增加系统的复杂度。

  3. 可能会降低代码的可读性:由于享元模式需要使用工厂类来管理共享对象,因此可能会降低代码的可读性。

    3、享元模式的应用场景

    享元模式的应用场景:

  1. 系统中存在大量相似对象,需要缓存这些对象以提高系统性能。

  2. 对象的创建和销毁需要消耗大量的资源,需要复用对象以减少资源消耗。

  3. 对象的状态可以分为内部状态和外部状态,其中内部状态可以共享,外部状态可以变化。

  4. 系统需要提供大量的小粒度对象,需要避免创建过多的对象,以减少内存消耗。

  5. 系统需要支持大量的细粒度对象,需要将对象的状态分为内部状态和外部状态,以实现对象的复用和共享。

    4、享元模式的结构

享元模式的结构包括以下几个角色:

  1. 抽象享元角色(Flyweight):定义享元对象的接口,同时可以接收外部状态作为参数。

  2. 具体享元角色(ConcreteFlyweight):实现抽象享元角色的接口,同时维护内部状态。

  3. 享元工厂角色(FlyweightFactory):负责创建和管理享元对象,维护享元池。

  4. 客户端角色(Client):使用享元对象的客户端,通过享元工厂角色获取享元对象,并传递外部状态。

    5、享元模式的代码案例

我们举一个游戏的例子来说明享元模式:

package com.pany.camp.design.principle.flyweigh;

/**
 *
 * @description:  抽象享元类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:19
 */
public interface Monster {
   
   
    void attack();
}
package com.pany.camp.design.principle.flyweigh;

import java.util.HashMap;
import java.util.Map;

/**
 * @description: 常量类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:21
 */
public class Constants {
   
   
    private static Map<String, Integer> attackMap = new HashMap<>();
    private static Map<String, Integer> defenseMap = new HashMap<>();

    static {
   
   
        attackMap.put("dragon", 100);
        attackMap.put("goblin", 50);
        attackMap.put("troll", 80);
        defenseMap.put("dragon", 80);
        defenseMap.put("goblin", 20);
        defenseMap.put("troll", 50);
    }

    public static int getAttack(String type) {
   
   
        return attackMap.get(type);
    }

    public static int getDefense(String type) {
   
   
        return defenseMap.get(type);
    }
}
package com.pany.camp.design.principle.flyweigh;

/**
 *
 * @description:  具体享元类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:20
 */
public class ConcreteMonster implements Monster {
   
   

    private String type; // 内部状态

    public ConcreteMonster(String type) {
   
   
        this.type = type;
    }

    @Override
    public void attack() {
   
   
        System.out.println("攻击力:" + Constants.getAttack(type) + ",防御力:" + Constants.getDefense(type));
    }
}
package com.pany.camp.design.principle.flyweigh;

import java.util.HashMap;
import java.util.Map;

/**
 * @description: 享元工厂类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:22
 */
public class MonsterFactory {
   
   

    private static Map<String, Monster> monsterMap = new HashMap<>();

    public static Monster getMonster(String type) {
   
   
        Monster monster = monsterMap.get(type);
        if (monster == null) {
   
   
            monster = new ConcreteMonster(type);
            monsterMap.put(type, monster);
        }
        return monster;
    }
}
package com.pany.camp.design.principle.flyweigh;

/**
 * @description: 客户端类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 21:22
 */
public class Client {
   
   

    public static void main(String[] args) {
   
   
        Monster dragon = MonsterFactory.getMonster("dragon");
        dragon.attack();
        Monster goblin = MonsterFactory.getMonster("goblin");
        goblin.attack();
        Monster troll = MonsterFactory.getMonster("troll");
        troll.attack();
        Monster dragon2 = MonsterFactory.getMonster("dragon");
        dragon2.attack();
    }
}

抽象享元类为 Monster ,具体享元类为 ConcreteMonster ,享元工厂类为 MonsterFactory ,常量类为 Constants ,客户端为 Client 。当需要创建怪物时,可以通过 MonsterFactory 来获取已经创建好的怪物对象,如果对象不存在则创建新的对象并放入享元池中。这样可以避免重复创建相同的对象,提高性能。

输出如下:

攻击力:100,防御力:80
攻击力:50,防御力:20
攻击力:80,防御力:50
攻击力:100,防御力:80

1686494501743.jpg

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊

1687869804912.jpg

目录
相关文章
|
3天前
|
设计模式 存储 Java
23种设计模式,享元模式的概念优缺点以及JAVA代码举例
【4月更文挑战第6天】享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享技术有效地支持大量细粒度对象的重用。这个模式在处理大量对象时非常有用,特别是当这些对象中的许多实例实际上可以共享相同的状态时,从而可以减少内存占用,提高程序效率
43 4
|
7月前
|
设计模式 存储 缓存
结构型设计模式07-享元模式
结构型设计模式07-享元模式
21 0
|
3天前
|
设计模式 存储 安全
二十三种设计模式全面解析-享元模式(Flyweight Pattern)详解:构建高效共享的对象结构
二十三种设计模式全面解析-享元模式(Flyweight Pattern)详解:构建高效共享的对象结构
|
3天前
|
设计模式
二十三种设计模式全面解析-组合模式与享元模式的结合应用:实现对象的共享和高效管理
二十三种设计模式全面解析-组合模式与享元模式的结合应用:实现对象的共享和高效管理
|
7月前
|
设计模式 存储 Java
【设计模式——学习笔记】23种设计模式——享元模式Flyweight(原理讲解+应用场景介绍+案例介绍+Java代码实现)
【设计模式——学习笔记】23种设计模式——享元模式Flyweight(原理讲解+应用场景介绍+案例介绍+Java代码实现)
29 0
|
3天前
|
设计模式 Java 开发者
【搞懂设计模式】享元模式:共享节约,皆大欢喜!
【搞懂设计模式】享元模式:共享节约,皆大欢喜!
7 0
|
3天前
|
设计模式 存储 Java
[设计模式Java实现附plantuml源码~结构型]实现对象的复用——享元模式
[设计模式Java实现附plantuml源码~结构型]实现对象的复用——享元模式
|
3天前
|
设计模式 Go
[设计模式 Go实现] 结构型~享元模式
[设计模式 Go实现] 结构型~享元模式
|
3天前
|
设计模式 存储 安全
【设计模式系列笔记】享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来最小化内存使用或计算开销,以提高性能。该模式适用于需要大量相似对象的场景,通过共享这些相似对象的部分状态,可以有效减少内存消耗。
35 0
|
3天前
|
设计模式 存储 Java
小谈设计模式(27)—享元模式
小谈设计模式(27)—享元模式