享元模式

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

类图示例

享元模式.png

举个例子

网站共享代码

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.util.HashMap;

//网站接口
interface WebSite{
void Use();
}
//具体网站
class ConcreteWebSite implements WebSite{
private String name="";
public ConcreteWebSite(String name){
this.name=name;
}
public void Use(){
System.out.println("网站分类"+name);
}
}
//网站工厂
class WebSiteFactory{
private HashMap<String,WebSite> webSiteMap=new HashMap<String,WebSite>();
public WebSite GetWebSite(String name){
if(!webSiteMap.containsKey(name)){
webSiteMap.put(name,new ConcreteWebSite(name));
}
return webSiteMap.get(name);
}
public int GetWebSiteCount(){
return webSiteMap.size();
}
}

public class FlyWeight {
public static void main(String[] args) {
WebSiteFactory factory=new WebSiteFactory();
WebSite fx=factory.GetWebSite("产品展示");
fx.Use();
WebSite fy= factory.GetWebSite("产品展示");
fy.Use();
WebSite fz=factory.GetWebSite("产品展示");
fz.Use();
WebSite f1= factory.GetWebSite("博客");
f1.Use();
WebSite f2= factory.GetWebSite("博客");
f2.Use();
WebSite f3= factory.GetWebSite("博客");
f3.Use();
System.out.println(factory.GetWebSiteCount());
}
}

类图

网站享元模式.png

享元模式包含如下角色

  1. Flyweight (抽象元类)
    抽象元类声明一个接口,通过它可以接受并作用于外部状态。在抽象元类中定义了具体元类公共的方法,这些方法可以向外界提供元对象的内部数据 (内部状态),同时也可以通过这些方法来设置外部数据 (外部状态)。
  2. ConcreteFlyweight (具体元类)
    具体元类实现了抽象元接口,实例称为元对象;在具体元类中为内部状态提供了存储空间,由于具体元对象必须是可以共享的,因此它所存储的状态必须是内部的,即它独立存在于自己的环境中。可以结合单例模式来设计具体元类,为每一个具体元类提供唯一的元对象。
  3. UnsharedConcreteFlyweight (非共享具体元类)
    并不是所有的抽象元类的子类都需要被共享,不能被共享的子类则设计为非共享具体元类;当需要一个非共享具体元类的对象时可以直接通过实例化创建;在某些享元模式的层次结构中,非共享具体元对象还可以将具体元对象作为子节点。
  4. FlyweightFactory (元工厂类)
    元工厂类用于创建并管理元对象;它针对抽象元类编程,将各种类型的具体元对象存储在一个元池中,元池一般设计为一个存储键值对的集合 (也可以是其他集合类型),可以结合工厂模式进行设计;当用户请求一个具体元对象时,元工厂提供一个存储在元池中已创建的实例或者创建一个新的实例 (如果不存在的话),返回该新创建的实例并将其存储在元池中。

模式分析

  • 优点
    1. 减少内存消耗:通过共享对象,减少了内存中对象的数量。
    2. 提高效率:减少了对象创建的时间,提高了系统效率。
  • 缺点
    1. 增加系统复杂度:需要分离内部状态和外部状态,增加了设计和实现的复杂性。
    2. 线程安全问题:如果外部状态处理不当,可能会引起线程安全问题。