01-考虑用静态工厂方法代替构造器
2017-01-15 18:22
477 查看
本文目录
简介
优势
缺点
服务提供者框架
下面是Java中自带的Boolean类(基本类型boolean的包装类)中的静态工厂方法,这个方法将基本类型boolean值转换成一个Boolean对象引用:
我们有两种方式获取Boolean的实例:
同样是传入true作为参数,两种方式有何差异?
一个类只能有一个带有指定签名的构造器。通过改变参数列表中参数的顺序,达到有多个构造函数的目的,显然这不是一个好主意。相比之下,静态工厂方法没有这个限制,对于指定签名,可以通过取不同的名称表示不同的构造方式,因此静态工厂方法进行对象实例化更加灵活。
2.不用每次调用静态工厂方法时创建一个新对象。
如果程序经常请求创建相同的对象,并且创建对象的代价很高,则它可以大幅提升性能。静态工厂方法能够为重复的调用返回相同对象,这样有助于类能严格控制某个时刻哪些实例应该存在,适用于单例模式。
3.在创建参数化类型实例时,使代码变得更加简洁。
当然,使用上面的静态工厂方法,前提是HashMap类中提供了这个静态工厂方法:
很遗憾,我看了HashMap类,至今也没有这个方法。
4.可以返回 原返回类型的任何子类型的对象。
静态工厂方法返回的对象所属的类,在编写包含该静态方法的类时可以没有,后来进行动态添加。这种灵活的方法构成了 服务提供者框架 ( Service Provider Framework)的基础,例如 JDBC API。服务提供者框架是指:多个服务提供者实现一个服务,系统为服务提供者的客户端实现多个实现,并把他们从多个实现中解耦处来。
2.它们与其他的静态方法实际上没有任何区别。
在API文档中,静态工厂方法并没有像构造器那样标识出来,因此,要查找是比较困难的,但是我们通过类/接口注释中关注静态工厂,并进行标准命名,也可以弥补这一缺憾,下面是一些惯用名称:
valueOf:该方法返回的实例与它的参数具有相同的值,实际上是类型转换方法,例如Boolean的;
of:这是valueOf的简洁替代。
getInstance:返回的实例是通过方法的参数来描述的,但是不能够说与参数具有相同的值。对于Singleton来说,该方法没有参数,并返回唯一的实例。
newInstance:像getInstance一样,但newInstance能够确保返回的每个实例都与所有其他实例不同。
getType:像getInstance一样,但是在工厂方法处于不同的类中的时候使用,Type表示工厂方法所返回的对象类型。
newType:像newInstance一样,但是在工厂方法处于不同的类中的时候使用,Type表示工厂方法所返回的对象类型。
以下例子模拟使用一卡通进出地铁
1.
2.
3.
4.
5.
6.测试类
看看测试类的代码,有没有像极了连接数据库的代码 O(∩_∩)O ~~
简介
优势
缺点
服务提供者框架
简介
如果想要获取一个类的实例,最常用的方法就是提供一个公有的构造器,除此之外,类还可以提供一个公有的静态工厂方法,它是一个返回类的实例的静态方法。下面是Java中自带的Boolean类(基本类型boolean的包装类)中的静态工厂方法,这个方法将基本类型boolean值转换成一个Boolean对象引用:
public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
我们有两种方式获取Boolean的实例:
//使用构造器 Boolean boolean1=new Boolean(true); //使用静态工厂方法 Boolean boolean2=Boolean.valueOf(true);
同样是传入true作为参数,两种方式有何差异?
优势
1.静态工厂方法拥有名称。一个类只能有一个带有指定签名的构造器。通过改变参数列表中参数的顺序,达到有多个构造函数的目的,显然这不是一个好主意。相比之下,静态工厂方法没有这个限制,对于指定签名,可以通过取不同的名称表示不同的构造方式,因此静态工厂方法进行对象实例化更加灵活。
2.不用每次调用静态工厂方法时创建一个新对象。
如果程序经常请求创建相同的对象,并且创建对象的代价很高,则它可以大幅提升性能。静态工厂方法能够为重复的调用返回相同对象,这样有助于类能严格控制某个时刻哪些实例应该存在,适用于单例模式。
3.在创建参数化类型实例时,使代码变得更加简洁。
//使用构造器 Map<Integer,String> map1=new HashMap<Integer,String>(); //使用静态工厂方法 Map<Integer,String> map2=HashMap.newInstance();
当然,使用上面的静态工厂方法,前提是HashMap类中提供了这个静态工厂方法:
public static <K,V>HashMap<K,V> newInstance(){ return new HashMap<K,V>(); }
很遗憾,我看了HashMap类,至今也没有这个方法。
4.可以返回 原返回类型的任何子类型的对象。
静态工厂方法返回的对象所属的类,在编写包含该静态方法的类时可以没有,后来进行动态添加。这种灵活的方法构成了 服务提供者框架 ( Service Provider Framework)的基础,例如 JDBC API。服务提供者框架是指:多个服务提供者实现一个服务,系统为服务提供者的客户端实现多个实现,并把他们从多个实现中解耦处来。
缺点
1.如果类中不存在非私有的构造器,就不能被子类化。2.它们与其他的静态方法实际上没有任何区别。
在API文档中,静态工厂方法并没有像构造器那样标识出来,因此,要查找是比较困难的,但是我们通过类/接口注释中关注静态工厂,并进行标准命名,也可以弥补这一缺憾,下面是一些惯用名称:
valueOf:该方法返回的实例与它的参数具有相同的值,实际上是类型转换方法,例如Boolean的;
of:这是valueOf的简洁替代。
getInstance:返回的实例是通过方法的参数来描述的,但是不能够说与参数具有相同的值。对于Singleton来说,该方法没有参数,并返回唯一的实例。
newInstance:像getInstance一样,但newInstance能够确保返回的每个实例都与所有其他实例不同。
getType:像getInstance一样,但是在工厂方法处于不同的类中的时候使用,Type表示工厂方法所返回的对象类型。
newType:像newInstance一样,但是在工厂方法处于不同的类中的时候使用,Type表示工厂方法所返回的对象类型。
服务提供者框架
以下例子模拟使用一卡通进出地铁
1.
/** * 进出地铁 服务定义接口 */ public interface SubWayInterface { // 进地铁 public boolean in(); // 出地铁 public boolean out(); }
2.
/** * 一卡通进出地铁 服务具体实现类 */ public class SubWayImpl implements SubWayInterface { public boolean in() { System.out.println("通过青岛一卡进地铁"); /** * 是否可以进入逻辑 */ return false; } public boolean out() { System.out.println("通过青岛一卡出地铁"); /** * 是否可以放行逻辑 */ return false; } }
3.
/** * 进出地铁 提供服务者接口 */ public interface SubwayProviderInterface { public SubWayInterface getService(); }
4.
/** * 进出地铁 提供服务者实现类 */ public class SubwayProviderImpl implements SubwayProviderInterface { static { ServiceManager.registerProvider("青岛一卡通", new SubwayProviderImpl()); } public SubWayInterface getService() { return new SubWayImpl(); } }
5.
/** * 服务提供者注册类 */ 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(name + "无效"); } return p.getService(); } }
6.测试类
public class Test { public static void main(String[] args) { try { Class.forName("ejava.SubwayProviderImpl"); SubWayInterface swi = ServiceManager.getService("青岛一卡通"); swi.in(); swi.out(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
看看测试类的代码,有没有像极了连接数据库的代码 O(∩_∩)O ~~
Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/student", "root", "root"); conn.createStatement(); ......
相关文章推荐
- 01、考虑用静态工厂方法代替构造器
- 改善JAVA代码01:考虑静态工厂方法代替构造器
- 《Effective Java》--01.考虑用静态工厂方法代替构造器
- 改善JAVA代码01:考虑静态工厂方法代替构造器
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Java学习笔记1:考虑用静态工厂方法代替构造器
- 【代码优化】考虑使用静态工厂方法代替构造器
- 第1条:考虑用静态工厂方法代替构造器
- Effective java读书札记第一条之 考虑用静态工厂方法代替构造器
- [Effective Java]01.用静态工厂方法代替构造器
- 考虑使用静态工厂方法代替构造器
- Effective JAVA NO1考虑用静态工厂方法代替构造器
- Effective Java (1) - 考虑用静态工厂方法代替构造器
- Android 编码规范:(一)考虑用静态工厂方法代替构造器
- [Effective Java]考虑用静态工厂方法代替构造器
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Android 编码规范:(一)考虑用静态工厂方法代替构造器
- Effective Java学习笔记之第1条 考虑用静态工厂方法代替构造器
- Effective Java(1)考虑静态工厂方法代替构造器
- 第一条:考虑用静态工厂方法代替构造器