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

Posted 技术趋势

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-服务定位器模式相关的知识,希望对你有一定的参考价值。

上文(设计模式-拦截过滤器模式):


背景

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

服务定位器模式是什么?

服务定位器模式(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

实现代码

/** * @Auther: csh * @Date: 2020/7/5 11:44 * @Description:抽象的服务接口 */public interface IUserInfo { public String getName(); public void printUserInfo();}
/** * @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 + '\'' + '}'; }}
/** * @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); }}
/** * @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); } }}
/** * @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; }}
/** * @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(); }}

结果

用户信息:user1用户信息:user2从缓存中获取到用户信息:User{userName='user1'}用户信息:user1

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

最后

参考文章:

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

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

以上是关于设计模式-服务定位器模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式服务定位器模式

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

你可以在graphql服务器模式文件中使用片段吗

服务定位器模式与抽象工厂模式有啥不同吗?

Unity设计模式—服务定位器模式

GoF--服务定位器模式