享元模式

概念

所谓享元模式就是运行共享技术有效地支持大量细粒度对象的复用。

目的

节省内存,对象复用。在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

使用场景

1、系统有大量相似对象。 2、需要缓冲池的场景。

个人理解

享元设计模式 = 工厂模式 + 单例模式

业务实践

个人案例

APP应用信息。比如极光推送,必须先在其开放平台注册一个APP应用,注册成功后,你将获取到一个AppId和AppSecret以及一个APP应用的英文名称。当需要对应用A进行消息推送的时候,需要构造一个极光推送的客户端对象,构造推送的设备信息以及推送的消息。当你只有一个APP应用,我们理所当然地使用单例设计模式即可解决API的调用问题,可是拥有多个APP应用的时候呢,传统思维是根据推送的设备信息,查询所属的APP应用,然后调用其API。其实这个时候,我们可以利用享元设计模式使得代码更加优雅。

代码如下
public class AppInfoFactory {

    private static final ConcurrentHashMap appInfoMap = new ConcurrentHashMap<>();

    /**
     * 享元设计模式 = 工厂模式 + 单例模式
     * 基于享元设计模式减少内存使用,复用对象
     * @param appName APP的名称唯一
     * @return APP对象实体
     */
    public static AppInfo getAppInfo(String appName) {
        Assert.state(appName != null, "应用名称不能为空!");
        AppInfo appInfo = appInfoMap.get(appName);
        if (appInfo == null) {
            IAppInfoService appInfoService = ApplicationSupport.getBean(IAppInfoService.class);
            appInfo = appInfoService.selectOne(new EntityWrapper().eq("app_name", appName));
            Assert.state(appInfo != null, "未找到名称为"+appName+"对应的APP的信息!");
            appInfoMap.put(appName,appInfo);
        }
        return appInfo;
    }

    /**
     * 添加|修改一个APP后,加入内存中进行复用
     * @param appInfo
     */
    public static void updateAppInfo(AppInfo appInfo){
        Assert.state(appInfo != null, "应用不能为空!");
        Assert.state(appInfo.getAppName() != null, "应用名称不能为空!");
        appInfoMap.put(appInfo.getAppName(),appInfo);
    }
}

工具类


/**
 * 获取Spring容器管理的Bean对象,应用中配置参数
 **/
@Component
public class ApplicationSupport implements DisposableBean, ApplicationContextAware {

    private static ApplicationContext applicationContext;
    // 获取配置文件参数值
    public static String getParamVal(String paramKey){
        return applicationContext.getEnvironment().getProperty(paramKey);
    }

    // 获取bean对象
    public static Object getBean(String name) {
        Assert.hasText(name);
        return applicationContext.getBean(name);
    }

    public static  T getBean(Class clazz) {
        return applicationContext.getBean(clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
   public void destroy() throws Exception {
        applicationContext = null;
    }
}

注意事项

不同于网上其他的享元模式的代码案例,此处,我做了很多的变更,但其目的仍然是对于对象的复用,内存的减少。
当在内存中查询没有发现需要的对象时,将从数据库查询,这样提高了拓展性。
因为存在新添加的APP信息,当程序在运行时,注册了一个新的客户端,那么内存中却并没有这个信息,那么我们将从数据库中查询,类似于缓存中没有,从数据库中查询。当存在管理页面,注册了一个APP应用后,实施人员添加到后端数据库表中时,可以调用静态方法updateAppInfo,添加到内存中。

你可能感兴趣的:(享元模式)