设计模式之享元模式(结构型)
Posted 一起来搬砖呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之享元模式(结构型)相关的知识,希望对你有一定的参考价值。
1、享元模式介绍
享元模式(Flyweight),主要用来减少创建对象的数量,以减少内存占用和提高性能。运用共享技术有效的支持持大量细粒度的对象。
- flyweight 是轻量级的意思,指拳击比赛中的特轻量级拳击手。这个设计模式的作用就是为了将对象变
轻
,也就是对象使用的内存大小。一般情况下需要大量对象使用new
进行创建,会消耗大量内存。 - 享元模式中可以共享的内容称为
内部状态
,需要外部环境来设置的不能共享的内容称为外部状态
。这两种状态是相互独立的,使用 flyweight 模式将一个对象的状态分为内部状态和外部状态,内部状态保持不变,共享不变的部分以达到减少内存占用的目的 - 支持大量细粒度对象是因为在实际程序中,能够共享的内部状态比较有限,所以享元对象一般都比较小,包含的内部状态较少,所以称之为细粒度对象
2、享元模式结构
享元模式角色:
-
Flyweight:享元接口,定义具体享元角色需要实现的方法,通过接口传入外部状态
/** * 享元接口 */ public interface Flyweight /** * 可以将外部状态作为参数传入方法,但不能改变方法的内部状态 */ void operator(String extrinsicStatus);
-
ConcreteFlyweight:具体享元对象,可共享内部状态,内部状态在创建时赋予,对象创建之后不再更改,外部状态使用参数传入
/** * 具体享元对象 */ public class ConcreteFlyweight implements Flyweight /** * 内部状态 */ private String internalStatus = null; public ConcreteFlyweight(String internalStatus) this.internalStatus = internalStatus; public ConcreteFlyweight() @Override public void operator(String extrinsicStatus) System.out.println("internalStatus = " + this.internalStatus); System.out.println("extrinsicStatus = " + extrinsicStatus);
-
UnsharedConcreteFlyweight:不需要共享的 Flyweight 子类,并不是所有的享元对象都可以共享,非共享的享元对象通常是享元对象的组合对象
/** * 不共享的享元对象 */ public class UnsharedConcreteFlyweight implements Flyweight @Override public void operator(String extrinsicStatus) System.out.println("不共享的 extrinsicStatus = " + extrinsicStatus);
-
FlyweightFactory:享元工厂角色,负责创建和管理享元角色
import java.util.HashMap; import java.util.Map; /** * 享元工厂 */ public class FlyweightFactory private Map<String, Flyweight> maps = new HashMap<>(); /** * 单例 */ private static FlyweightFactory instance = new FlyweightFactory(); public static FlyweightFactory getInstance() return instance; /** * 根据 key 获取享元对象 */ public Flyweight getFlyweight(String key) // 先从缓存中获取对象,对象不存在则创建对象放入容器中 if (!maps.containsKey(key)) maps.put(key, new ConcreteFlyweight()); return maps.get(key);
-
调用方
public class FlyweightClient public static void main(String[] args) FlyweightFactory factory = FlyweightFactory.getInstance(); Flyweight flyweightA = factory.getFlyweight("A"); flyweightA.operator("A"); Flyweight flyweightB = factory.getFlyweight("B"); flyweightB.operator("B"); UnsharedConcreteFlyweight unsharedConcreteFlyweight = new UnsharedConcreteFlyweight(); unsharedConcreteFlyweight.operator("C"); // internalStatus = null // extrinsicStatus = A // internalStatus = null // extrinsicStatus = B // 不共享的 extrinsicStatus = C
3、享元模式使用场景
- 程序使用了大量的对象,这些大量的对象对内存的压力会比较大的时候可以考虑使用
- 对象的大部分状态是外部状态的话,删除对象的外部状态,可以用相对较少的共享对象取代多组对象的话,可以使用共享模式。
比如下棋游戏,一盘棋局可以下很多棋子,常规思维的话每个棋子都是一个对象,每局都会产生很多对象。使用 flyweight 模式的话,棋子的颜色一般是比较少而且不变的,颜色可以作为内部状态,棋子的区别在于它们的位置不同,棋子的坐标可以作为外部状态,这样的话棋子对象最多可以减少到两个实例。
字符串 String 就运用了 flyweight,创建相同的字符串时,会将后创建的字符串的引用指向先创建的字符串,实现字符串再内存中的共享
4、享元模式优缺点
- 享元模式可以有效的支持大量细粒度的对象
- 使用享元模式需要维护一个记录了系统已有的所有享元的容器,而且为了使对象共享,将一些状态外部化,程序的逻辑可能会变得复杂。最好在足够多的对象实例可供共享的时候才使用享元模式
以上是关于设计模式之享元模式(结构型)的主要内容,如果未能解决你的问题,请参考以下文章