设计模式之-享元模式,快速掌握享元模式,通俗易懂的讲解享元模式以及它的使用场景

news/2024/7/21 4:14:06 标签: 设计模式, 享元模式, java

文章目录

  • 一、快速理解享元模式
  • 二、使用场景
  • 三、优缺点
    • 优点:
    • 缺点:
  • 四、示例代码
  • 我们来看一个故事,加深一下理解
  • 当使用享元模式时,我们可以总结如下:


一、快速理解享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来最大限度地减少内存使用和提高性能。它适用于需要创建大量相似对象的情况,通过共享相同的状态来减少对象的数量,从而节省内存和提高系统的效率。

通俗易懂的解释: 想象一下,你在一个游戏中扮演军队指挥官,需要管理成千上万的士兵。每个士兵都有自己的外观、武器等属性,如果每个士兵都创建一个独立的对象,将会消耗大量的内存。而享元模式就像是在军队里共享相同外观的士兵,节省了内存空间。

二、使用场景

享元模式适用于以下情况:

  1. 系统中存在大量相似对象,并且这些对象可以共享相同的状态。
  2. 对象的大部分状态可以外部化,并且可以通过参数传递给对象。

三、优缺点

优点:

  1. 减少内存消耗:通过共享相同状态的对象,减少了需要创建的对象数量,从而节省了内存空间。
  2. 提高性能:由于减少了对象数量,可以减少对内存的频繁操作,提高系统的性能。
  3. 增加对象复用性:通过共享对象,可以在不同的上下文中重复使用对象,提高了对象的复用性。

缺点:

  1. 共享对象的状态是不可变的:由于多个对象共享相同的状态,如果一个对象的状态发生改变,可能会影响到其他对象,因此共享的状态应该是不可变的。
  2. 对象共享可能导致线程安全问题:如果多个线程同时访问共享对象并修改其状态,可能会导致线程安全问题,需要进行适当的同步处理。

四、示例代码

下面是一个简单的示例代码来说明享元模式的应用:

假设我们要创建一个文字处理器,需要处理大量的文本字符。为了节省内存,我们希望共享相同字符的对象。

首先,我们定义一个接口 TextCharacter,表示文本字符:

java">public interface TextCharacter {
    void display();
}

然后,我们实现具体的文本字符类 ConcreteCharacter,包含一个字符属性 character:

java">public class ConcreteCharacter implements TextCharacter {
    private char character;

    public ConcreteCharacter(char character) {
        this.character = character;
    }

    @Override
    public void display() {
        System.out.println("Character: " + character);
    }
}

接下来,我们创建一个工厂类 CharacterFactory,用于管理和共享文本字符对象。它包含一个字符对象池 characterPool,使用 HashMap 来存储共享的字符对象:

java">public class CharacterFactory {
    private Map<Character, TextCharacter> characterPool;

    public CharacterFactory() {
        characterPool = new HashMap<>();
    }

    public TextCharacter getCharacter(char character) {
        TextCharacter textCharacter = characterPool.get(character);

        if (textCharacter == null) {
            textCharacter = new ConcreteCharacter(character);
            characterPool.put(character, textCharacter);
        }

        return textCharacter;
    }
}

最后,我们可以使用享元模式来创建和展示文本字符:

java">public class TextProcessor {
    public static void main(String[] args) {
        CharacterFactory characterFactory = new CharacterFactory();

        TextCharacter charA = characterFactory.getCharacter('A');
        charA.display();

        TextCharacter charB = characterFactory.getCharacter('B');
        charB.display();

        TextCharacter charA2 = characterFactory.getCharacter('A');
        charA2.display();
    }
}

在上述示例中,我们使用享元模式来共享相同的文本字符对象。通过工厂类 CharacterFactory 来管理对象池,并根据需要返回共享的对象。在 TextProcessor 类中,我们获取了三个字符对象:‘A’、‘B’ 和 ‘A’,其中第一个和第三个对象是相同的,通过共享对象来节省内存空间。

我们来看一个故事,加深一下理解

假设你是一个游戏开发者,正在开发一个角色扮演游戏。在游戏中,有许多不同类型的怪物,每个怪物都有自己的外观和属性。为了提高游戏的性能和减少内存占用,你决定使用享元模式来管理怪物对象。

在游戏中,有三种类型的怪物:巨人、骷髅和史莱姆。每个怪物都有自己的外观和属性,例如巨人有高耐力和强力攻击,骷髅具有高速度和弱攻击,史莱姆则具有低耐力和中等攻击。

为了实现享元模式,首先你需要创建一个抽象的怪物类 Monster,它包含了共享的状态和行为:

java">public abstract class Monster {
    protected String appearance;
    protected int health;
    protected int attack;

    public void display() {
        System.out.println("Appearance: " + appearance);
        System.out.println("Health: " + health);
        System.out.println("Attack: " + attack);
    }

    public abstract void attack();
}

然后,你可以实现具体的怪物类,包括巨人、骷髅和史莱姆。这些具体的怪物类只需实现它们特定的属性,而共享的属性则可以在抽象类中定义:

java">public class GiantMonster extends Monster {
    public GiantMonster() {
        appearance = "Giant";
        health = 100;
        attack = 50;
    }

    @Override
    public void attack() {
        System.out.println("Giant monster is attacking!");
    }
}

public class SkeletonMonster extends Monster {
    public SkeletonMonster() {
        appearance = "Skeleton";
        health = 50;
        attack = 10;
    }

    @Override
    public void attack() {
        System.out.println("Skeleton monster is attacking!");
    }
}

public class SlimeMonster extends Monster {
    public SlimeMonster() {
        appearance = "Slime";
        health = 20;
        attack = 20;
    }

    @Override
    public void attack() {
        System.out.println("Slime monster is attacking!");
    }
}

接下来,你需要创建一个怪物工厂类 MonsterFactory,用于管理和共享怪物对象。它包含一个怪物对象池 monsterPool,使用 HashMap 来存储共享的怪物对象:

java">public class MonsterFactory {
    private Map<String, Monster> monsterPool;

    public MonsterFactory() {
        monsterPool = new HashMap<>();
    }

    public Monster getMonster(String type) {
        Monster monster = monsterPool.get(type);

        if (monster == null) {
            switch (type) {
                case "giant":
                    monster = new GiantMonster();
                    break;
                case "skeleton":
                    monster = new SkeletonMonster();
                    break;
                case "slime":
                    monster = new SlimeMonster();
                    break;
                default:
                    throw new IllegalArgumentException("Invalid monster type!");
            }

            monsterPool.put(type, monster);
        }

        return monster;
    }
}

最后,你可以使用享元模式来创建和展示怪物:

java">public class Game {
    public static void main(String[] args) {
        MonsterFactory monsterFactory = new MonsterFactory();

        Monster giant1 = monsterFactory.getMonster("giant");
        giant1.display();

        Monster skeleton = monsterFactory.getMonster("skeleton");
        skeleton.display();

        Monster slime1 = monsterFactory.getMonster("slime");
        slime1.display();

        Monster giant2 = monsterFactory.getMonster("giant");
        giant2.display();
    }
}

在上述示例中,我们使用享元模式来共享相同的怪物对象。通过工厂类 MonsterFactory 来管理对象池,并根据需要返回共享的对象。在 Game 类中,我们获取了四个怪物对象:巨人、骷髅、史莱姆和另一个巨人。其中第一个和最后一个怪物对象是相同的,通过共享对象来节省内存空间。

通过这个故事中的角色扮演游戏的例子,希望你能更好地理解享元模式的概念和应用,以及它如何通过共享对象来减少内存消耗和提高性能。

当使用享元模式时,我们可以总结如下:

  1. 享元模式的目标是通过共享对象来减少内存使用和提高性能。
  2. 享元模式适用于需要创建大量相似对象的情况。
  3. 享元模式通过将对象的共享状态外部化,使得多个对象可以共享相同的状态,从而减少了对象的数量。
  4. 共享状态是不可变的,如果一个对象的状态发生改变,可能会影响到其他对象。
  5. 享元模式的核心是一个工厂类,用于管理和共享对象。
  6. 工厂类通过对象池来存储共享的对象,使用合适的数据结构(如HashMap)来实现快速查找和存储。
  7. 客户端通过工厂类获取共享对象,并可以根据需要设置对象的非共享状态。
  8. 享元模式可以减少内存消耗、提高系统性能,并增加对象的复用性。
  9. 在多线程环境下使用享元模式时,需要考虑线程安全问题,并进行适当的同步处理。
    总之,享元模式通过共享相同状态的对象来减少内存占用,提高性能,并增加对象的复用性。它适用于需要创建大量相似对象的场景,特别是当对象的大部分状态可以外部化时。

http://www.niftyadmin.cn/n/5288359.html

相关文章

RFID技术在汽车制造:提高生产效率、优化物流管理和增强安全性

RFID技术在汽车制造:提高生产效率、优化物流管理和增强安全性 随着科技的进步&#xff0c;物联网技术已经深入到各个领域&#xff0c;尤其在制造业中&#xff0c;RFID技术以其独特的优势&#xff0c;如高精度追踪、实时数据收集和自动化操作&#xff0c;正在改变传统的生产方式…

企微私域工具:打造高效客户管理新模式

随着互联网的快速发展&#xff0c;企业微信私域工具逐渐成为企业客户管理的新宠。这种工具通过建立企业微信私域流量池&#xff0c;帮助企业更好地管理和维护客户关系&#xff0c;提高客户满意度和忠诚度。本文将介绍企微私域工具的概念、优势、应用场景以及如何选择合适的企微…

【Azure 架构师学习笔记】- Power Platform(1) - 简介

本文属于【Azure 架构师学习笔记】系列。 本文属于【Power Platform】系列。 Power Platform 它是一个SaaS平台&#xff0c;支持和延伸M365&#xff0c; Dynamics 365和Azure甚至其他第三方服务。主要提供低代码&#xff0c;自动化&#xff0c;数据驱动和定制化业务逻辑的服务…

亚马逊云科技 re:Invent 2023 产品体验:亚马逊云科技产品应用实践 王炸产品 Amazon Q,你的 AI 助手

意料之中 2023年9月25日&#xff0c;亚马逊宣布与 Anthropic 正式展开战略合作&#xff0c;结合双方在更安全的生成式 AI 领域的先进技术和专业知识&#xff0c;加速 Anthropic 未来基础模型的开发&#xff0c;并将其广泛提供给亚马逊云科技的客户使用。 亚马逊云科技开发者社…

KEPServerEX 6 之 GE Ethernet 连接FANUC ROBOT机器人实战

GE Ethernet Driver 连接FANUC ROBOT机器人 ---------------------------- GE Fanuc介绍 GE Fanuc是GE公司控制系统部门的一部分,成立于1998年。其主要业务涵盖工业自动化、控制系统、PLC和组态软件等领域。其产品可用于包括自动化、过程自动化、国防、汽车制造、通讯、医疗…

Unity中Shader裁剪空间推导(正交相机到裁剪空间的转化矩阵)

文章目录 前言一、正交相机视图空间 转化到 裁剪空间 干了什么1、正交相机裁剪的范围主要是这个方盒子2、裁剪了之后&#xff0c;需要把裁剪范围内的坐标值化到[-1,1]之间&#xff0c;这就是我们的裁剪空间。3、在Unity中&#xff0c;设置相机为正交相机4、在这里设置相机的近裁…

JVM钩子

JVM钩子 简介 在Java应用程序中&#xff0c;可以通过注册关闭钩子&#xff08;Shutdown Hook&#xff09;函数来实现在JVM关闭时执行特定的代码。关闭钩子是一种用于在JVM关闭时执行清理任务的机制&#xff0c;它允许开发者在JVM关闭之前执行一些必要的清理工作&#xff0c;如…

华锐视点为广汽集团打造VR汽车在线展厅,打破地域限制,尽享购车乐趣

随着科技的飞速发展&#xff0c;我们正在进入一个全新的时代——元宇宙时代。元宇宙是一个虚拟的世界&#xff0c;它不仅能够模拟现实世界&#xff0c;还能够创造出现实世界无法实现的事物。而汽车行业作为人类生活的重要组成部分&#xff0c;也在积极探索与元宇宙的融合&#…