什么是享元模式?

JavaScript016

什么是享元模式?,第1张

    享元模式主要是为了解决大量对象创建后,增大了系统的资源开销,为了解决此问题,该模式通过共享对象的方式实现。

    接下来,以一个实际例子来简单介绍下享元模式,假设有这么一个场景有两个用户服务类,分别是普通用户服务与VIP用户服务,其中有个Operation操作,而该操作主要是为了完成用户注册过程,在注册过程中,需要通过调用短信接口来完成注册流程;这时两个用户服务都需要一个HTTP连接池来完成此功能;如果每个类都单独创建一个HTTP连接池,那么系统将会产生两份资源开销,而其利用率将会很低;

    为此,通过如下图例中的设计方式,将HTTP连接池的在用户服务工厂中进行创建,通过抽象工厂模式建立多种不同的用户服务子类实现,并将HTTP连接池在子类实例间进行共享,实现降低资源开销,提升连接池的资源利用率。

又称 FlyWeight,代表轻量级的意思,结构型设计模式。

享元模式是对象池的一种实现。类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能。享元模式也是为了减少内存的使用,避免出现大量重复的创建销毁对象的场景。

享元模式用在一批相同或相似的对象上,这些对象有可以共享的内部状态和各自不同的外部状态。

享元模式中会有一个工厂,工厂维护着一个容器,容器以键值对的方式存储,键是对象的内部状态,也就是共享的部分,值就是对象本身。客户端从这个工厂获取对象,如果容器中存在这个对象就直接返回,不存在再创建新的对象并存入容器,避免了大量重复创建对象。

使用共享对象有效的支持大量的细粒度对象的复用。

系统中存在大量的 相似对象。

细粒度的对象都具备较接近的外部状态,且内部状态与环境无关,即对象没有特定身份。

需要 缓冲池 的场景。

例1. 过年回家买火车票,无数人在客户端上订票 (有多次购票、刷票的情况),即不断向服务端发送请求。

而每次查询,服务器必须做出回应,具体地,用户查询输入出发地和目的地,查询结构返回值只有一趟列车的车票。而数以万计的人有同样需求,即不间断请求数据,每次重新创建一个查询的车票结果,即造成大量重复对象创建、销毁,使得服务器压力加重。

享元模式正好适合解决该情形的问题,例如 A 到 B 地的车辆是有限的,车上铺位分硬卧、软卧和坐票三种,将这些可公用的对象缓存起来。用户查询时优先使用缓存,反之则重新创建。

我们知道 Java 中 String 是存在于常量池中,即一个 String 被定义之后它就被缓存到了常量池中,当其他地方使用同样的字符串,则直接使用缓存,而非创建。

享元模式的优缺点

优点 - 大幅度地降低内存中对象的数量。

缺点-1) 为了使对象可共享,需将一些状态外部化,使程序的逻辑复杂化

享元模式可以理解成一组共享的对象集合,下面就是一个简单的享元设计模式(甚至可以说是工厂模式了,呵呵,工厂模式目的是将具体创建对象的过程由工厂方法提供,用户只需要知道抽象类型即可。但这个例子就不要纠结成工厂模式了)

private Map<String, Object>map = new HashMap<String, Object>

public Object get(String key) {

if(map.containsKey(key)) {

return map.get(key)

}

Object obj = new Object()

map.put(key, obj)

return obj

}

单例模式见下

public class S {

private static S s = new S()

private S() {

}

public static S getInstance() {

return s

}

}

从上面我们享元设计模式是一个类有很多对象,而单例是一个类仅一个对象;享元模式是为了节约内存空间,提升程序性能(避免大量的new操作);而单例模式则主要是出于共享状态的目的