享元模式(上)
享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。
具体来讲,当一个系统中存在大量重复对象的时候,如果这些重复的对象是不可变对象,我 们就可以利用享元模式将对象设计成享元,在内存中只保留一份实例,供多处代码引用。这 样可以减少内存中对象的数量,起到节省内存的目的。
享元模式的两个应用场景
1、在象棋游戏中,每一句的棋子都是一样的,当有多个玩家时,不同玩家之间只是象棋的位置不同,那么我们就可以将一些基础的属性抽出来,供多个人使用,节省了内存。
2、文本编辑器中,每一个字体都可以单独的设置格式。对于字体格式,我们可以将它设计成享元,让不同的文字共享使用。
享元模式 vs 单例、缓存、对象池
享元模式跟单例的区别
在单例模式中,一个类只能创建一个对象,而在享元模式中,一个类可以创建多个对象,每 个对象被多处代码引用共享。实际上,享元模式有点类似于之前讲到的单例的变体:多例
应用享元模式是为了对象复用,节省内存,而应用单例模式是为 了限制对象的个数。
享元模式跟缓存的区别
在享元模式的实现中,我们通过工厂类来“缓存”已经创建好的对象。这里的“缓存”实际 上是“存储”的意思,跟我们平时所说的“数据库缓存”“CPU 缓存”“MemCache 缓 存”是两回事。我们平时所讲的缓存,主要是为了提高访问效率,而非复用。
享元模式跟对象池的区别
为了避免频繁地进行对象创 建和释放导致内存碎片,我们可以预先申请一片连续的内存空间,也就是这里说的对象池。每次创建对象时,我们从对象池中直接取出一个空闲对象来使用,对象使用完成之后,再放 回到对象池中以供后续复用,而非直接释放掉。
池化技术中的“复用”可以理解为“重复使用”,主要目的是节省时间(比如从数据库池中 取一个连接,不需要重新创建)。在任意时刻,每一个对象、连接、线程,并不会被多处使 用,而是被一个使用者独占,当使用完成之后,放回到池中,再由其他使用者重复利用。
享元模式中的“复用”可以理解为“共享使用”,在整个生命周期中,都是被所有使用者共享 的,主要目的是节省空间。
参考
《设计模式之美》