简述-享元模式
介绍
享元的主旨在共享,既然共享了,那么就好处就是可以复用了,它的英文名叫Flyweight,轻量级的意思,通过共享的方式来节省内存开销。
其目的是达到部分状态可共享,可共享的状态为内部状态(不随外部环境改变),不可共享为外部状态(可随外部环境改变)。原理即是做缓存对象处理。
比如Android中的Message,推荐使用handler的obtain方法来获取一个message,这种方式获取的message是从message池里获取出来使用的,当使用完成之后,又recycle放回message池里,默认池大小为50,回收的时候,如果池里小于50个则放入池中,使用时从中取出,Message是使用链表方式存储。
UML
使用场景
- 系统中存在大量相似对象
- 细粒度对象有较接近的外部状态,且与内部状态无关,也就是说对象没有特定身份(就像Message,外部都是Message,内部携带的值完全可变)
- 需要缓冲池的场景
事例
就比如系统中有消息对象到处都需要使用,那么就满足来系统中存在大量相似的对象,就可以采用缓存策略来节省内存了
- 建立消息接口:提供更改内部消息,和获取消息方法
/**
* 享元模式
*/
public interface IMessage {
/**
* 设置消息对象携带的消息
*
* @param info
*/
void setInfo(String info);
/**
* 获取消息
*/
String getInfo();
}
- 消息实体,实现消息接口
/**
* 享元模式消息对象
*/
public class Message implements IMessage {
private String info;
@Override
public void setInfo(String info) {
this.info = info;
}
@Override
public String getInfo() {
return this.info;
}
}
- 建立工厂接口:提供回收消息方法,获取消息方法
/**
* 享元模式工厂:
* 1.取缓存对象,存缓存对象
* 2. 回收缓存对象
*/
public interface IMessageFactory {
/**
* 消息对象使用完后,进行回收可再利用
*/
void recycle(IMessage iMessage);
/**
* 获取一个消息对象
*
* @return 消息对象
*/
IMessage obtainMessage();
}
- 建立实体工厂:该工厂全局使用,用了单例模式,内部使用一个列表来进行缓存,列表缓存数量控制为2个
/**
* 消息缓存工厂
*/
public class MessageFactory implements IMessageFactory {
/**
* 缓存的列表
*/
private List<IMessage> messageCacheList = new ArrayList<>(2);
public static IMessageFactory getInstance() {
return MyHolder.MESSAGE_FACTORY;
}
/**
* 回收,加到列表中,可再复用
*
* @param iMessage
*/
@Override
public void recycle(IMessage iMessage) {
synchronized (messageCacheList) {
messageCacheList.add(iMessage);
}
}
/**
* 获取消息对象
*
* @return 缓存的消息对象或者是新建的消息对象
*/
@Override
public IMessage obtainMessage() {
synchronized (messageCacheList) {
if (messageCacheList.size() > 0) {
System.out.println("缓存有数据,从缓存中获取");
return messageCacheList.remove(0);
}
System.out.println("缓存没数据,新建返回");
IMessage iMessage = new Message();
return iMessage;
}
}
private static class MyHolder {
private static final MessageFactory MESSAGE_FACTORY = new MessageFactory();
}
}
- 测试Client
public static void main(String[] arg) {
System.out.println("获取+回收");
for (int i = 0; i < 3; i++) {
//获取消息并回收
IMessage iMessage = MessageFactory.getInstance().obtainMessage();
iMessage.setInfo("消息" + i);
System.out.println(iMessage.getInfo());
MessageFactory.getInstance().recycle(iMessage);
}
System.out.println("只获取");
//只获取不回收
for (int i = 0; i < 3; i++) {
//获取消息并回收
IMessage iMessage = MessageFactory.getInstance().obtainMessage();
iMessage.setInfo("消息" + i);
System.out.println(iMessage.getInfo());
}
}
- 输出
获取+回收
缓存没数据,新建返回
消息0
缓存有数据,从缓存中获取
消息1
缓存有数据,从缓存中获取
消息2
只获取
缓存有数据,从缓存中获取
消息0
缓存没数据,新建返回
消息1
缓存没数据,新建返回
消息2
通过一个列表来缓存,使用完了进行回收,这样就达到了一个简单的消息缓存操作,也可以控制缓存的量。
总结:享元模式的实现方式多种多样,Android中的Message就在Message对象中实现了recycle方法,通过链表方式引用缓存对象。主要是一个思想,目的是一样的,就是达到缓存共享复用