享元模式 理解及代码案例

怎么理解享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,用于有效地支持大量细粒度的对象共享,以减少内存消耗和提高性能。

在某些情况下,如果系统中存在大量相似对象,并且这些对象的大部分状态是可以共享的,传统的对象创建方式会导致内存消耗过大。享元模式通过共享对象的内部状态来减少对象的数量,从而节省内存。

享元模式的核心思想是将对象分为两部分:内部状态(Intrinsic State)和外部状态(Extrinsic State)。

内部状态:内部状态是对象可以共享的部分,它独立于具体场景,可以在多个对象之间共享。内部状态存储在享元对象内部,并且在运行时不会改变。

外部状态:外部状态是对象特定于场景的部分,它在运行时可能会变化。外部状态不能被共享,需要在使用时通过参数传递给享元对象。

享元模式的关键是将对象的创建和共享分离开来。享元工厂(Flyweight Factory)负责管理和创建享元对象。当需要使用享元对象时,客户端通过享元工厂获取对象,并提供外部状态作为参数。享元工厂会检查内部状态是否已存在,如果存在则返回共享的对象,如果不存在则创建一个新的对象并缓存起来供后续使用。

经典案例:线程池

在线程池中,线程对象可以被看作是享元对象,而线程池可以看作是享元工厂。

线程池通过预先创建一组可复用的线程对象,并根据需要将任务分配给这些线程来执行,从而减少了线程的创建和销毁开销。这里的线程对象就是享元对象,而线程池则扮演着享元工厂的角色。

在线程池中,线程的内部状态是固定的,例如线程的运行状态、优先级、线程组等,并且这些状态在线程的整个生命周期中保持不变。这些内部状态可以被多个任务共享,因此可以被看作是享元对象的内部状态。

而线程的外部状态则是每个任务特定的,例如任务的具体执行代码、输入参数等。外部状态通过任务对象传递给线程池,线程池根据任务的外部状态来执行具体的任务。

当线程池接收到一个任务时,它会从池中获取一个空闲的线程,并将任务的外部状态传递给该线程。线程根据接收到的外部状态执行任务,并在任务完成后返回到线程池中等待下一个任务。这样,通过复用线程对象并共享线程的内部状态,线程池实现了对线程的有效管理和利用。

总结起来,线程池体现了享元模式的思想,通过共享线程对象的内部状态和复用线程对象,减少了线程的创建和销毁开销,降低了系统资源的消耗,提高了系统的性能和响应能力。

经典案例:字符缓存池

在某些应用中,需要频繁地操作字符对象,例如在文本编辑器中对字符进行插入、删除、替换等操作。在这种情况下,每次都创建新的字符对象会导致内存消耗较大,而且频繁的创建和销毁字符对象也会降低性能。

享元模式可以通过共享已经创建的字符对象来解决这个问题。具体实现时,可以使用一个字符缓存池来存储已经创建的字符对象。当需要操作字符时,首先检查字符缓存池中是否已经存在该字符对象,如果存在则直接使用,如果不存在则创建新的字符对象并将其加入缓存池,以便后续复用。

下面是一个简单的示例代码,展示了如何使用享元模式来实现字符缓存池:

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

public class CharacterPool {
    private Map<Character, Character> pool;

    public CharacterPool() {
        pool = new HashMap<>();
    }

    public Character getCharacter(char c) {
        if (pool.containsKey(c)) {
            return pool.get(c);
        } else {
            Character character = new Character(c);
            pool.put(c, character);
            return character;
        }
    }
}

// 在使用时,可以通过字符缓存池获取字符对象,并进行相关操作
CharacterPool characterPool = new CharacterPool();
Character a = characterPool.getCharacter('a');
Character b = characterPool.getCharacter('b');
Character c = characterPool.getCharacter('c');
// ...

在上面的代码中,CharacterPool 类代表字符缓存池,使用 HashMap 来存储已经创建的字符对象。getCharacter() 方法用于获取字符对象,首先检查缓存池中是否已经存在该字符对象,如果存在则直接返回,如果不存在则创建新的字符对象并加入缓存池。这样就可以实现字符对象的复用,避免了频繁地创建和销毁字符对象。

通过使用享元模式,字符缓存池可以大幅减少内存消耗,并提高相关操作的性能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值