后浪 来学习吧!设计模式【08】享元模式
2020-07-02 本文已影响0人
BubbleWonder
设计模式【08】享元模式
定义
运用共享技术有效地支持大量细粒度的对象。
主要解决什么
在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
结构
- 抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
- 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
- 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
- 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
图中的 UnsharedConcreteFlyweight 是非享元角色,里面包含了非共享的外部状态信息 info;而 Flyweight 是抽象享元角色,里面包含了享元方法 operation(UnsharedConcreteFlyweight state),非享元的外部状态以参数的形式通过该方法传入;ConcreteFlyweight 是具体享元角色,包含了关键字 key,它实现了抽象享元接口;FlyweightFactory 是享元工厂角色,它逝关键字 key 来管理具体享元;客户角色通过享元工厂获取具体享元,并访问具体享元的相关方法。
实现
package flyweight;
import java.util.HashMap;
public class FlyweightPattern
{
public static void main(String[] args)
{
FlyweightFactory factory=new FlyweightFactory();
Flyweight f01=factory.getFlyweight("a");
Flyweight f02=factory.getFlyweight("a");
Flyweight f03=factory.getFlyweight("a");
Flyweight f11=factory.getFlyweight("b");
Flyweight f12=factory.getFlyweight("b");
f01.operation(new UnsharedConcreteFlyweight("第1次调用a。"));
f02.operation(new UnsharedConcreteFlyweight("第2次调用a。"));
f03.operation(new UnsharedConcreteFlyweight("第3次调用a。"));
f11.operation(new UnsharedConcreteFlyweight("第1次调用b。"));
f12.operation(new UnsharedConcreteFlyweight("第2次调用b。"));
}
}
//非享元角色
class UnsharedConcreteFlyweight
{
private String info;
UnsharedConcreteFlyweight(String info)
{
this.info=info;
}
public String getInfo()
{
return info;
}
public void setInfo(String info)
{
this.info=info;
}
}
//抽象享元角色
interface Flyweight
{
public void operation(UnsharedConcreteFlyweight state);
}
//具体享元角色
class ConcreteFlyweight implements Flyweight
{
private String key;
ConcreteFlyweight(String key)
{
this.key=key;
System.out.println("具体享元"+key+"被创建!");
}
public void operation(UnsharedConcreteFlyweight outState)
{
System.out.print("具体享元"+key+"被调用,");
System.out.println("非享元信息是:"+outState.getInfo());
}
}
//享元工厂角色
class FlyweightFactory
{
private HashMap<String, Flyweight> flyweights=new HashMap<String, Flyweight>();
public Flyweight getFlyweight(String key)
{
Flyweight flyweight=(Flyweight)flyweights.get(key);
if(flyweight!=null)
{
System.out.println("具体享元"+key+"已经存在,被成功获取!");
}
else
{
flyweight=new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
}
return flyweight;
}
}
程序运行结果如下:
具体享元a被创建!
具体享元a已经存在,被成功获取!
具体享元a已经存在,被成功获取!
具体享元b被创建!
具体享元b已经存在,被成功获取!
具体享元a被调用,非享元信息是:第1次调用a。
具体享元a被调用,非享元信息是:第2次调用a。
具体享元a被调用,非享元信息是:第3次调用a。
具体享元b被调用,非享元信息是:第1次调用b。
具体享元b被调用,非享元信息是:第2次调用b。
Android中的应用
Message.obtainMessage通过重用Message对象来避免大量的Message对象被频繁的创建和销毁。
String;ServiceManager。
总结
优点:
大大减少对象的创建,降低系统的内存,使效率提高。
缺点:
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
使用场景:
1、系统有大量相似对象。
2、需要缓冲池的场景。
注意事项:
1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。
2、这些类必须有一个工厂对象加以控制。