前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式-服务定位器模式

设计模式-服务定位器模式

作者头像
逍遥壮士
发布2020-09-18 11:32:51
6820
发布2020-09-18 11:32:51
举报
文章被收录于专栏:技术趋势技术趋势

背景

记得刚入行的时候,有一个需求通过用户每次来获取一个固定商品的信息,而我的实现是直接从库中查出再转成对象,然后返回给用户,突然某一天用户量增加了好几百倍,直接把库拉挂了...后面直接用上了缓存,解决了该问题...

服务定位器模式是什么?

服务定位器模式(Service Locator Pattern)用在我们想使用 JNDI 查询定位各种服务的时候。考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术。在首次请求某个服务时,服务定位器在 JNDI 中查找服务,并缓存该服务对象。当再次请求相同的服务时,服务定位器会在它的缓存中查找,这样可以在很大程度上提高应用程序的性能。

角色:

服务(Service):实际处理请求的服务。对这种服务的引用可以在 JNDI 服务器中查找到。

Context / 初始的 Context :JNDI Context 带有对要查找的服务的引用。

服务定位器(Service Locator):服务定位器是通过 JNDI 查找和缓存服务来获取服务的单点接触。

缓存(Cache):缓存存储服务的引用,以便复用它们。

客户端(Client):Client 是通过 ServiceLocator 调用服务的对象。

优点:

提升系统性能:由于该模式可以将每次需要返回的固定数据放到缓存中可以减少每次创建对象的开销,很大程度上提升了系统的性能;

缺点:

缓存的实现使系统会比较复杂,如果控制不好会导致内存溢出。

服务定位器模式可以干嘛?

服务定位器模式主要解决一个相同或者公共的数据放到缓存中减少内存开销,并且在一定程序上提升了系统的性能。

个人理解:

比如数据库连接池,不需要每次去连接数据库的时候去创建连接,而是由池去保持一些连接,当需要连接数据库的时候直接获取池中的连接就可以了。

服务定位器模式类图

源码下载:https://gitee.com/hong99/design-model/issues/I1IMES

实现代码

代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/7/5 11:44
 * @Description:抽象的服务接口
 */
public interface IUserInfo {
    public String getName();
    public void printUserInfo();
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/7/5 11:45
 * @Description:用户信息(Service)
 */
public class User implements IUserInfo {
    private String userName;


    public void setUserName(String userName) {
        this.userName = userName;
    }

    private User() {
    }



    public User(String usreName) {
        this.userName = usreName;
    }

    @Override
    public String getName() {
        return userName;
    }

    @Override
    public void printUserInfo() {
        System.out.println("用户信息:"+this.getName());
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                '}';
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/7/5 11:48
 * @Description:创建对象(Context )
 */
public class InitialContext {
    private static InitialContext initialContext = new InitialContext();

    private InitialContext(){

    }

    public static InitialContext getInstance(){
        return initialContext;
    }

    public Object lookup(String username){
        return new User(username);
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/7/5 11:51
 * @Description:用户缓存
 */
public class UserCache {
    private List<IUserInfo> userInfos;

    public UserCache() {
        userInfos = new ArrayList <IUserInfo>();
    }

    public IUserInfo getUserInfo(String userName){
        for (IUserInfo userInfo : userInfos) {
            if(userInfo.getName().equalsIgnoreCase(userName)){
                System.out.println("从缓存中获取到用户信息:"+userInfo.toString());
                return userInfo;
            }
        }
        return null;
    }

    public void addUserInfo(IUserInfo userInfo){
        boolean exist = false;
        for (IUserInfo info : userInfos) {
            if(info.getName().equalsIgnoreCase(userInfo.getName())){
                exist = true;
            }
        }
        if(!exist){
            userInfos.add(userInfo);
        }
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/7/5 12:06
 * @Description:服务定位器(Service Locator)
 */
public class UserInfoLocator {
    private static UserCache userCache = new UserCache();

    public static IUserInfo getUserInfo(String userName){
        IUserInfo userInfo = userCache.getUserInfo(userName);
        if(userInfo!=null){
            return userInfo;
        }
        InitialContext instance = InitialContext.getInstance();
        IUserInfo user  = (IUserInfo)instance.lookup(userName);
        userCache.addUserInfo(user);
        return user;
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/7/5 12:51
 * @Description:服务定位器模式
 */
public class Client {
    public static void main(String[] args) {
        IUserInfo userInfo = UserInfoLocator.getUserInfo("user1");
        userInfo.printUserInfo();
        userInfo = UserInfoLocator.getUserInfo("user2");
        userInfo.printUserInfo();
        userInfo = UserInfoLocator.getUserInfo("user1");
        userInfo.printUserInfo();
    }
}

结果

代码语言:javascript
复制
用户信息:user1
用户信息:user2
从缓存中获取到用户信息:User{userName='user1'}
用户信息:user1

源码下载:https://gitee.com/hong99/design-model/issues/I1IMES

最后

服务定位器模式就是将公共或者频繁使用的信息放到缓存中,然后当用户再去获取的时候可以直接从缓存中获取,减少系统开辟内存空间的开销并且可以提升系统性能,大幅度提升资源的利用率。该模式开发中无处不用数据库连接池中的数据库连接、配置信息(账号、密码、连接地址)放到缓存中、spring的一些bean注入等,但是该模式要注意放入缓存中的信息需要添加过期时候,否则可能缓存越堆越大会导致内存溢出问题...

参考文章:

https://www.oracle.com/technetwork/java/servicelocator-137181.html

http://gameprogrammingpatterns.com/service-locator.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术趋势 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档