享元模式
是指重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
单纯享元模式
是指所有的享元对象都是可以直接共享的,它的构成如下:
1、抽象享元(Flyweight) :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
2、具体享元(ConcreteFlyweight):实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间
3、享元工厂(FlyweightFactory) :负责创建和管理享元角色。当一个客户端对象调用一个享元对象的时候,享元工厂会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象,享元工厂角色就应当创建一个合适的享元对象。
复合享元模式
是指将一些单纯享元使用合成模式加以复合,形成复合享元对象的模式。复合享元对象本身不能共享,但是它可以分解成可以共享的单纯享元对象。它的构成如下:
1、抽象享元(Flyweight) :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
2、具体享元(ConcreteFlyweight):实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间
3、复合享元(ConcreteCompositeFlyweight) :复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。
4、享元工厂(FlyweightFactory) :负责创建和管理享元角色。当一个客户端对象调用一个享元对象的时候,享元工厂会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象,享元工厂角色就应当创建一个合适的享元对象。
ps:目前来说没有找到复合享元模式的应用场景,貌似有点多余,你知到有哪些非它不可的应用场景么?
优点:
1、可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能
2、享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享
缺点:
1、在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式
2、使系统变得复杂, 需要 享元对象分离出外部状态和内部状态,内部状态保持不变,外部状态能给外部调用者修改并保存状态的副本
使用场景:1、系统有大量相似对象(但能够被划分为有限的几个分类),容易造成内存的大量耗费的场景。 2、需要缓冲池的场景
例如线程池的使用,java的常量池,百度网盘上传电影的场景等
实现原理:
核心原理:使用 HashMap 或者类似的数据结构来缓存维护这些对象,形成一个缓冲池
单纯享元模式的创建步骤
步骤一:创建抽象享元接口
public interface ShareBeanInterface{
//一个示意性方法,参数state是外蕴状态
void operateOutside(String state)
}
步骤二:创建共享元实例
public class ShareBean implements ShareBeanInterface{
private object obj;//内蕴状态,外部能引用但不能修改,只提供getter
public String state;//外蕴状态,外部能引用能修改
void operateOutside(String state){
this.state=state;
}
// 省略的getter和setter..
}
步骤三:实现共享元工厂(建议结合单例模式使用工厂)
public class ShareFactory{
private Map<keyName, ShareBean > beans = new HashMap<>();
private static ShareFactory instance;
private ShareFactory(){
}
public static ShareFactory getInstance(){
if(instance==null){
instance=new ShareFactory();
}
return instance;
}
public ShareBean createByName(String keyName){
ShareBean bean=beans .get(keyName);
if(bean==null){
bean=new ShareBean ()
}
return bean;
}
}
步骤四:使用
ShareBean bean=ShareFactory.getInstance(). createByName("eqer");
复杂享元模式的创建步骤(不建议使用)
步骤一:创建抽象享元接口
public interface ShareBeanInterface{
//一个示意性方法,参数state是外蕴状态
void operateOutside(String state)
}
步骤二:创建共享元实例
public class ShareBean implements ShareBeanInterface{
private object obj;//内蕴状态,外部能引用但不能修改,只提供getter
public String state;//外蕴状态,外部能引用能修改
void operateOutside(String state){
this.state=state;
}
// 省略的getter和setter..
}
步骤三:创建复杂共享元实例
public class CompositeShareBean implements ShareBeanInterface{
private Map beans;
public CompositeShareBean (){
beans=newHashMap<>();
}
// 增加一个新的单纯享元对象到聚集中
public void add(String key, ShareBean bean){
beans.put(key,bean);
}
@Override
public void operation(String state){
ShareBean bean;
for(String str: beans.keySet()) {
bean= beans.get(str);
bean.operation(state);
}
}
}
步骤四:实现共享元工厂(需同时具有生产单纯共享元与复杂共享元的方法)
public class CompositeShareFactory{
private Map beans = new HashMap<>();
private static ShareFactory instance;
private ShareFactory(){
}
public static ShareFactory getInstance(){
if(instance==null){
instance=new ShareFactory();
}
return instance;
}
public ShareBean createByName(String keyName){
ShareBean bean=beans .get(keyName);
if(bean==null){
bean=new ShareBean ()
}
return bean;
}
public CompositeShareBean createByNames(List<String> compositeKeyName){
CompositeShareBean compositeShareBean=new CompositeShareBean ();
for(String keyName : compositeKeyName ) {
compositeShareBean.add(state,this.createByName( keyName ));
}
compositeShareBean;
}
}
步骤四:使用(略,不建议使用)
网友评论