第1条:考虑用静态工厂方法代替构造器
来源:互联网 发布:淘宝品牌排行榜 编辑:程序博客网 时间:2024/06/07 10:09
转载http://liwenshui322.iteye.com/blog/1267202
Java 服务提供者框架介
服务提供者框架是指:多个服务提供者实现一个服务,系统为客户端提供多个实现,并把他们从多个实现中解耦出来。服务提供者的改变对它们的客户端是透明的,这样提供了更好的可扩展性。例如,JDBC,JMS等就是用了服务提供者框架。
他们之间的关系如下图:
1.服务具体实现类和服务提供者实现类是服务提供者自己去实现。以JDBC为例,这2个模块由具体的数据库提供商来实现。
2.其他三个模块是java对数据库提供商怎么实现上面2个模块的一个约束。比如:提供服务者实现类必须实现服务提供者接口。才能成功注册到服务提供者注册类。以JDBC为例,所有的数据库提供商只需要按照接口里面定义的规则来操作,都能成功地使java连上他们的数据库。
下面以mysql数据库为例简单说明一下mysql数据库提供商是如何实现这些接口的。
1.我们在java中获取mysql连接对象源代码如下:
Class.forName("com.mysql.jdbc.Driver"); DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123");
从这个地方可以看出:我们只需要更换数据库的驱动名称与建立连接的URL,用户名等信息,就可以完全切换到另外一个数据库。数据库底部怎么操作的我们不清楚,也没必要清楚。我们获取的连接对象是Connection,查看java.sql.Connection这个类,会发现它只是一个接口。我们得到的只是一个接口,怎么可能能够操作数据库呢?其实这里得到的不是Connection接口,而是它的一个实现类,只是对于客户端不可见而已。这可能就是所谓的面向接口编程,客户端只需要知道它该知道的信息,服务端告诉客户端,你可以调用哪些方法。至于具体方法怎么实现是服务端的事情,客服端就不需要管,也不需要知道了。
下面我们看看简单的这2个语句分别做了什么事情:
语句一: Class.forName(“…”)。这样一个语句会实例化一个com.mysql.jdbc.Driver类(提供服务者实现类),并将这个类的实例注册到DriverManager(服务提供者注册类)。
语句二: 通过建立连接的URL,用户名,密码来获取建立到mysql数据库的连接。是这样的,DriverManager通过你传进来的url信息判断出你是要获取那个服务提供者提供的服务。也就是语句一已经将提供服务者实现类注册到DriverManager了,DriverManager获取到这个服务提供者实现类对象之后,通过调用它的getService(mysql里面是connect方法)方法获取到服务具体实现类对象,返回的却是java.sql.Connection接口对象(因为服务具体实现类实现了Connection接口),这样把服务具体实现类对象隐藏了。提供了很好的扩展性。
最后,我们自己来测试一个。
以北京地铁进出控制为例:现在北京地铁进出都是刷卡,有二种卡:1.一卡通(比如一次性冲值50元,进地铁刷一次,出地铁刷一次,扣2元)。2.一次性卡(进地铁刷一次,出地铁插入回收。)这2种卡都可以实现进出地铁功能,但实现的具体方法是有区别的:一卡通:需要获取这卡余额是多少,然后扣掉2元。如果余额不足2元怎么处理等。一次性卡则没必要了。
(1)服务定义接口 -> 平台:
/** * 进出地铁服务接口 * @author Administrator * */ public interface SubWayInterface { //进入地铁 public boolean in(); //出地铁 public boolean out(); }
(2)服务具体实现类 -> 供应商:
/** * 一卡通地铁进出服务实现 * @author Administrator * */ public class SubWayImpl implements SubWayInterface { public boolean in() { System.out.println("通过一卡通进入地铁"); /** * 进行一些处理,然后返回是否放行 */ return false; } public boolean out() { System.out.println("通过一卡通出地铁"); /** * 进行一些处理,然后返回是否放行 */ return false; } }
(3) 提供服务者接口 -> 平台:
/** * 地铁进出服务提供者接口 * @author Administrator * */ public interface SubwayProviderInterface { public SubWayInterface getService(); }
(4) 提供服务者实现类 -> 供应商:
/** * 服务提供者实现类 * @author Administrator * */ public class SubwayProviderImpl implements SubwayProviderInterface { static { ServiceManager.registerProvider("一卡通", new SubwayProviderImpl()); } public SubWayInterface getService() { return new SubWayImpl(); } }
(5) 服务提供者注册类 -> 平台:
/** * 服务提供者注册类 * * @author Administrator * */ public class ServiceManager { private ServiceManager() { } private static final Map<String, SubwayProviderInterface> providers = new ConcurrentHashMap<String, SubwayProviderInterface>(); public static void registerProvider(String name, SubwayProviderInterface p) { providers.put(name, p); } public static SubWayInterface getService(String name) { SubwayProviderInterface p = providers.get(name); if (p == null) { throw new IllegalArgumentException( "No provider registered with name:" + name); } return p.getService(); } }
(6) 客户端测试类:
/** * 客户端测试类 * @author Administrator * */ public class Test { /** * @param args * @throws ClassNotFoundException */ public static void main(String[] args) throws ClassNotFoundException { Class.forName("cn.netjava.cgl.subway.SubwayProviderImpl"); SubWayInterface swi = ServiceManager.getService("一卡通"); swi.in(); swi.out(); } }
测试类Class.forName(”“)里面的参数你可能跟我的不同,看你服务提供者实现类放在哪个包下面了。
-> PS : 博主根据上面这篇文章,自己实现了单次乘车卡的消费模式。然后,大家也可以在这个场景下,通过实现不同的卡,来了解熟悉服务者框架,并将其运用在未来可能的工作中。
- 第1条:考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第1条 考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器(第一章:创建和销毁对象)
- 《Effective java》读书记录-第1条-考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第1条、考虑用静态工厂方法代替构造器
- 第1条 考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- Effective Java 中文版之学习 第1条:考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- 第一条:考虑用静态工厂方法代替构造器
- 第一条:考虑用静态工厂方法代替构造器
- 不存在具有“AppType”的“IEnumerable<SelectListItem>”类型的 ViewData 项
- Android中layer-list使用详解
- CDOJ1073-秋实大哥与线段树 线段树单点更新+区间求和
- ssh框架小结
- angular-file-upload 封装为指令获取图片高宽
- 第1条:考虑用静态工厂方法代替构造器
- C/C++中的static
- Arcgis engine 将两个Geometry对象合并为一个新的Geometry对象,其中GeometryA的值会被修改
- Android 屏幕适配:最全面的解决方案
- 2017(一)linux基础命令
- Scala 学习笔记(四)------定义递归函数
- PS 中的7种投影技
- Unity中使用 slua --- 调用c#方法
- FFmpeg再学习 -- FFmpeg解码知识