使用依赖注入能够消除MovieLister对具体实现MovieFinder的依赖。这允许我把Movielister
但注入并不是解除依赖关系的唯一方法,还有一种方法也可以解除依赖关系,那就是使用服务定位器模式。
模式内容
服务定位器的最基本的思想就是有一个对象定位器知晓如何控制应用程序需要的所有服务。所以根据Lister&Finder例子提到的应用程序的一个服务定位器在需要的时候将会使用某个方法返回一个movie finder的实例。当然这仅仅是转移一些负担而已,我们仍旧必须取得进入lister的服务定位器,结果就呈现以下的依赖关系。
模式示例
MovieFinder finder = ServiceLocator.movieFinder();
class ServiceLocator...
public static MovieFinder movieFinder() {
return soleInstance.movieFinder;
}
private static ServiceLocator soleInstance;
private MovieFinder movieFinder;
就像注入方法一样,我们必须配置服务定位器(class ServiceLocator...)。下面我用代码来完成这个功能,但是使用从配置文件读取相应数据的机制也并不困难。
class Tester...
private void configure() {
ServiceLocator.load(new ServiceLocator(new ColonMovieFinder("movies1.txt")));
}
class ServiceLocator...
public static void load(ServiceLocator arg) {
soleInstance = arg;
}
public ServiceLocator(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
class Tester...
public void testSimple() {
configure();
MovieLister lister = new MovieLister();
Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
assertEquals("Once Upon a Time in the Wes", movies[0].getTitle());
}
在对ServiceLocator的具体实现上还有很多技巧可以使用,
1.在初始化方式上,可以采用子类继承父类的方式,在父类初始化阶段 就得到 静态对象
2.还可以通过接口的方式返回一个movieFinder 这样 具体实现跟实际调用就通过接口隔离开了
3.还可以通过线程相关的存储机制来提供线程相关的定位器
4.还可以将几种movieFinder的实现,放入到Map中,动态的生成实例,以构建动态定位器
模式实现
import javax.naming.*;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.ejb.EJBHome;
import javax.ejb.EJBLocalHome;
import javax.sql.DataSource;
import java.util.*;
import java.sql.*;
/** *//**
* 实现 service locater 模式,用于由客户端来调用以通过JNDI查
* 找相关的 ejb或是其它服务的入口.
* */
public final class ServiceLocater {
protected static ServiceLocater inst = new ServiceLocater();
private InitialContext ic = null;
private Map ejbHomeCache = null;
private Map dataSourceCache = null;
protected ServiceLocater() {
try {
dataSourceCache = Collections.synchronizedMap(new HashMap());
ejbHomeCache = Collections.synchronizedMap(new HashMap());
ic = new InitialContext();
}
catch (Exception e) {
e.printStackTrace();
}
}
/** *//**
* 取得 servicelocater的单子实例.
* */
synchronized public static ServiceLocater getInstance() {
return inst;
}
/** *//**
*查找并返回一个数据源
* @param name String 数据源名称
* @return DataSource ,查找不到则抛出异常.
* @throws NamingException ,查找不到或是类型不对。
* */
private DataSource lookUpDataSource(String name) throws NamingException {
DataSource tmpDS = (DataSource)this.dataSourceCache.get(name);
if (tmpDS == null) {
try {
tmpDS = (DataSource)this.ic.lookup(name);
this.dataSourceCache.put(name, tmpDS);
}
catch (NamingException namE) {
throw namE;
}
catch (Exception otherE) {
throw new NamingException(otherE.getMessage());
}
}
return tmpDS;
}
/** *//**
* 查找并返回一个远程接口
* @param jndiHomeName ebj名字
* @param className ejb类名字
* @return
* @throws ServiceLocatorException
*/
public EJBHome getRemoteHome(String jndiHomeName, Class className) throws
ServiceLocatorException {
EJBHome home = (EJBHome)this.ejbHomeCache.get(jndiHomeName);
if (home == null) {
try {
Object objref = ic.lookup(jndiHomeName);
Object obj = PortableRemoteObject.narrow(objref, className);
home = (EJBHome) obj;
this.ejbHomeCache.put(jndiHomeName, home);
}
catch (NamingException ne) {
throw new ServiceLocatorException(ne);
}
catch (Exception e) {
throw new ServiceLocatorException(e);
}
}
return home;
}
/** *//**
* 查找并返回一个本地接口
* @param jndiHomeName jndiHomeName名字
* @return 一个本地接口
* @throws ServiceLocatorException
*/
public EJBLocalHome getLocalHome(String jndiHomeName) throws
ServiceLocatorException {
EJBLocalHome home = null;
try {
home = (EJBLocalHome) ic.lookup(jndiHomeName);
}
catch (NamingException ne) {
throw new ServiceLocatorException(ne);
}
catch (Exception e) {
throw new ServiceLocatorException(e);
}
return home;
}
/** *//**
*查找一个数据源,并取得一个连接.
* @param name String 数据源名称
* @return DataSource ,查找不到则抛出异常.
* @throws NamingException ,查找不到或是类型不对。
* */
public Connection getConnection(String DataSourceJNDIName) throws
SQLException {
try {
Connection conn = this.lookUpDataSource(DataSourceJNDIName).getConnection();
conn.setAutoCommit(false);
//conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
return conn;
}
catch (Exception e) {
e.printStackTrace();
throw new SQLException(e.getMessage());
}
}
}
分享到:
相关推荐
.NET 服务器定位模式(Service Locator Pattern)——Common Service Locator-附件资源
服务定位器模式(Service Locator Pattern)用在我们想使用 JNDI 查询定位各种服务的时候。考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术。在首次请求某个服务时,服务定位器在 JNDI 中...
安装labview之后,如何解决NI service locator is not running
Autofac的ServiceLocator模式应用,零配置
Locatable是一个Swift微框架,它利用Property Wrappers通过自定义属性@Locatable实现Service Locator模式
Ckode.ServiceLocator Ckode.ServiceLocator是一个简单的本机实现的服务定位器,用于简化依赖项注入。 例子: 创建一个实例: var locator = new ServiceLocator();ISomeInterface instance = locator....
这是关于服务定位器模式的初学者教程。虽然服务定位器模式目前非常不受欢迎,并且被依赖注入容器的使用推到了一边,但看看它提供了什么以及为什么它现在被认为不足仍然很有趣。
本文中,作者深入探索IOC模式的工作原理,给它一个更能描述其特点的名字——“依赖注入”(Dependency Injection),并将其与“服务定位器”(Service Locator)模式作一个比较。不过,这两者之间的差异并不太重要,...
感谢菜鸟教程为我们大家做出的无私奉献。结合菜鸟教程实例,和Java设计模式(国外)...对设计模式进行自我学习。提供自我见解,源码文件。 希望有不好的地方多加理性批评,以便及时改正。
用Java实现23种设计模式 1. 创建型模式 工厂模式(Factory Pattern) ... 服务定位器模式(Service Locator Pattern) 传输对象模式(Transfer Object Pattern) 生产者消费者模式(Producer Consumer Pattern)
该文件解释了IServiceLocator实现必须正确实现以符合此接口的预期语义,以及一些实现注意事项。 规格 GetInstance(Type, string) 这是从容器中检索单个实例的核心方法。 此方法不得返回null。...
服务定位器 服务定位器违反了封装,隐藏了正确使用的前提条件。 是一种反模式。 是一种模式,允许我们开发松耦合代码。 结果 Get cached! services.Servicio1 Creating a new services.Servicio1 instance. Put ...
参考Yii2实现的以依赖注入为基础的服务定位器,Yii2代码部分为vendor / yiisoft / yii2 / di /依赖注入DI依赖注入知道怎么初始化对象,只需配置构造参数就可以,核心代码如下(简化,只是说思路) class Di { //经过...
ts-service-locator 服务定位器模式是一种防止组件与其依赖的服务之间的硬性依赖的模式。 有关更多信息,请参。 ts-service-locator是使用服务定位器模式的解决方案,具有类型安全性。 使用它来注册全局使用的服务并...
字——“依赖注入”(Dependency Injection),并将其与“服务定位器”(Service Locator) 模式作一个比较。不过,这两者之间的差异并不太重要,更重要的是:应该将组件的配置与使用 分离开——两个模式的目标都是...
服务定位器.NET IoC 容器和服务定位器
用于JavaScript中IoC的轻量服务定位器 要求 Locator需要Map的实现,可以从babel-core以polyfill的形式获得 用法 使用定位器动态检索服务和其他组件的共享实例。 Locator能够按类型(例如,构造函数)和名称注册模块...