1、考虑用静态工厂方法代替构造器(effective java)
2016-06-07 14:35
435 查看
目录检索
考虑静态构造方法
优点
第一个优势是有名称
不必每次调用都创建一个新的对象
可以返回原类型的任何子类
服务者提供框架
在创建泛型的时候可以使代码更简单
缺点
类如果不含有公有的或者受保护的构造器就不能被子类化
与其他静态方法没有任何区别不像构造函数那样地位很高
第1条:考虑用静态工厂方法代替构造器
第2条:遇到多个构造器参数时要考虑用构建器
第3条:用私有构造器或者枚举类型强化Singleton属性
第4条:通过私有构造器强化不可实例化的能力
第5条:避免创建不必要的对象
第6条:消除过期的对象引用
第7条:避免使用终结方法
第3章 对于所有对象都通用的方法
第8条:覆盖equals时请遵守通用约定
第9条:覆盖equals时总要覆盖hashCode
第10条:始终要覆盖toString
第11条:谨慎地覆盖clone
第12条:考虑实现Comparable接口
第4章 类和接口
第13条:使类和成员的可访问性最小化
第14条:在公有类中使用访问方法而非公有域
第15条:使可变性最小化
第16条:复合优先于继承
第17条:要么为继承而设计,并提供文档说明,要么就禁止继承
第18条:接口优于抽象类
第19条:接口只用于定义类型
第20条:类层次优于标签类
第21条:用函数对象表示策略
第22条:优先考虑静态成员类
第5章 泛型
第23条:请不要在新代码中使用原生态类型
第24条:消除非受检警告
第25条:列表优先于数组
第26条:优先考虑泛型
第27条:优先考虑泛型方法
第28条:利用有限制通配符来提升API的灵活性
第29条:优先考虑类型安全的异构容器
第6章 枚举和注解
第30条:用enum代替int常量
第31条:用实例域代替序数
第32条:用EnumSet代替位域
第33条:用EnumMap代替序数索引
第34条:用接口模拟可伸缩的枚举
第35条:注解优先于命名模式
第36条:坚持使用Override注解
第37条:用标记接口定义类型
第7章 方法
第38条:检查参数的有效性
第39条:必要时进行保护性拷贝
第40条:谨慎设计方法签名
第41条:慎用重载
第42条:慎用可变参数
第43条:返回零长度的数组或者集合,而不是:null
第44条:为所有导出的API元素编写文档注释
第8章 通用程序设计
第45条:将局部变量的作用域最小化
第46条:for-each循环优先于传统的for循环
第47条:了解和使用类库
第48条:如果需要精确的答案,请避免使用float和double
第49条:基本类型优先于装箱基本类型
第50条:如果其他类型更适合,则尽量避免使用字符串
第51条:当心字符串连接的性能
第52条:通过接口引用对象
第53条:接口优先于反射机制
第54条:谨慎地使用本地方法
第55条:谨慎地进行优化
第56条:遵守普遍接受的命名惯例
第9章 异常
第57条:只针对异常的情况才使用异常
第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常
第59条:避免不必要地使用受检的异常
第60条:优先使用标准的异常
第61条:抛出与抽象相对应的异常
第62条:每个方法抛出的异常都要有文档
第63条:在细节消息中包含能捕获失败的信息
第64条:努力使失败保持原子性
第65条:不要忽略异常
第10章 并发
第66条:同步访问共享的可变数据
第67条:避免过度同步
第68条:executor和task优先干线程
第69条:并发工具优先于wait和notify
第70条:线程安全性的文档化
第71条:慎用延迟初始化
第72条:不要依赖于线程调度器
第73条:避免使用线程组
第11章 序列化
第74条:谨慎地实现Serializable接口
第75条:考虑使用自定义的序列化形式
第76条:保护性地编写readObject方法
第77条:对于实例控制,枚举类型优先于readResolve
第78条:考虑用序列化代理代替序列化实例
测试
考虑静态构造方法
优点
第一个优势是有名称
不必每次调用都创建一个新的对象
可以返回原类型的任何子类
服务者提供框架
在创建泛型的时候可以使代码更简单
缺点
类如果不含有公有的或者受保护的构造器就不能被子类化
与其他静态方法没有任何区别不像构造函数那样地位很高
目录检索
第2章 创建和销毁对象第1条:考虑用静态工厂方法代替构造器
第2条:遇到多个构造器参数时要考虑用构建器
第3条:用私有构造器或者枚举类型强化Singleton属性
第4条:通过私有构造器强化不可实例化的能力
第5条:避免创建不必要的对象
第6条:消除过期的对象引用
第7条:避免使用终结方法
第3章 对于所有对象都通用的方法
第8条:覆盖equals时请遵守通用约定
第9条:覆盖equals时总要覆盖hashCode
第10条:始终要覆盖toString
第11条:谨慎地覆盖clone
第12条:考虑实现Comparable接口
第4章 类和接口
第13条:使类和成员的可访问性最小化
第14条:在公有类中使用访问方法而非公有域
第15条:使可变性最小化
第16条:复合优先于继承
第17条:要么为继承而设计,并提供文档说明,要么就禁止继承
第18条:接口优于抽象类
第19条:接口只用于定义类型
第20条:类层次优于标签类
第21条:用函数对象表示策略
第22条:优先考虑静态成员类
第5章 泛型
第23条:请不要在新代码中使用原生态类型
第24条:消除非受检警告
第25条:列表优先于数组
第26条:优先考虑泛型
第27条:优先考虑泛型方法
第28条:利用有限制通配符来提升API的灵活性
第29条:优先考虑类型安全的异构容器
第6章 枚举和注解
第30条:用enum代替int常量
第31条:用实例域代替序数
第32条:用EnumSet代替位域
第33条:用EnumMap代替序数索引
第34条:用接口模拟可伸缩的枚举
第35条:注解优先于命名模式
第36条:坚持使用Override注解
第37条:用标记接口定义类型
第7章 方法
第38条:检查参数的有效性
第39条:必要时进行保护性拷贝
第40条:谨慎设计方法签名
第41条:慎用重载
第42条:慎用可变参数
第43条:返回零长度的数组或者集合,而不是:null
第44条:为所有导出的API元素编写文档注释
第8章 通用程序设计
第45条:将局部变量的作用域最小化
第46条:for-each循环优先于传统的for循环
第47条:了解和使用类库
第48条:如果需要精确的答案,请避免使用float和double
第49条:基本类型优先于装箱基本类型
第50条:如果其他类型更适合,则尽量避免使用字符串
第51条:当心字符串连接的性能
第52条:通过接口引用对象
第53条:接口优先于反射机制
第54条:谨慎地使用本地方法
第55条:谨慎地进行优化
第56条:遵守普遍接受的命名惯例
第9章 异常
第57条:只针对异常的情况才使用异常
第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常
第59条:避免不必要地使用受检的异常
第60条:优先使用标准的异常
第61条:抛出与抽象相对应的异常
第62条:每个方法抛出的异常都要有文档
第63条:在细节消息中包含能捕获失败的信息
第64条:努力使失败保持原子性
第65条:不要忽略异常
第10章 并发
第66条:同步访问共享的可变数据
第67条:避免过度同步
第68条:executor和task优先干线程
第69条:并发工具优先于wait和notify
第70条:线程安全性的文档化
第71条:慎用延迟初始化
第72条:不要依赖于线程调度器
第73条:避免使用线程组
第11章 序列化
第74条:谨慎地实现Serializable接口
第75条:考虑使用自定义的序列化形式
第76条:保护性地编写readObject方法
第77条:对于实例控制,枚举类型优先于readResolve
第78条:考虑用序列化代理代替序列化实例
考虑静态构造方法
这里的静态构造方法不等于设计模式中的工厂模式public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
优点:
第一个优势是有名称
对于同一个对象,它的构造函数名字是确定的,有时候你需要基于这个类的自定义对象,采用这种静态构造方法,命名的时候可以很清楚的把这个对象的特点说清楚。不必每次调用都创建一个新的对象
你可以缓存起来,进行重复利用,每次返回的时候都返回同一个对象,如上面的代码所示,并没有使用new,直接返回的是已经有的对象可以返回原类型的任何子类
适用于基于接口的框架。而且可以使API返回的对象的类是私有的(使用构造函数肯定不行)。服务者提供框架
静态工厂方法返回的对象所属的类,在编写包含该静态工厂方法的类时可不存在,构成了服务者提供框架//服务提供者接口,用来提供服务 //这个接口时可选的,如果没有,下面的Map集合就可以直接存放Service对象 public interface Provider { Service newService(); }
//服务接口, 用来写具体的服务内容 public interface Service { // Service-specific methods go here }
public class Services { private Services() { } // Prevents instantiation (Item 4) // Maps service names to services //服务的注册和访问 //用一个Map来存放提供这的名字和提供者的对象 private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>(); public static final String DEFAULT_PROVIDER_NAME = "<def>"; // Provider registration API //注册默认的提供者 public static void registerDefaultProvider(Provider p) { registerProvider(DEFAULT_PROVIDER_NAME, p); } //所谓注册就是在加入Map public static void registerProvider(String name, Provider p) { providers.put(name, p); } // Service access API //使用这个方法创建实例 public static Service newInstance() { return newInstance(DEFAULT_PROVIDER_NAME); } //创建的时候看缓存里有没有provider public static Service newInstance(String name) { Provider p = providers.get(name); if (p == null) throw new IllegalArgumentException( "No provider registered with name: " + name); return p.newService(); } }
测试
public class Test { public static void main(String[] args) { //测试的时候先注册,然后在再创建相应地对象,这里的provider的使用内部类 //由provider返回具体的service实例 // Providers would execute these lines Services.registerDefaultProvider(DEFAULT_PROVIDER); Services.registerProvider("comp", COMP_PROVIDER); Services.registerProvider("armed", ARMED_PROVIDER); // Clients would execute these lines //调用Service的toString方法 Service s1 = Services.newInstance(); Service s2 = Services.newInstance("comp"); Service s3 = Services.newInstance("armed"); System.out.printf("%s, %s, %s%n", s1, s2, s3); } private static Provider DEFAULT_PROVIDER = new Provider() { public Service newService() { return new Service() { @Override public String toString() { return "Default service"; } }; } }; private static Provider COMP_PROVIDER = new Provider() { public Service newService() { return new Service() { @Override public String toString() { return "Complementary service"; } }; } }; private static Provider ARMED_PROVIDER = new Provider() { public Service newService() { return new Service() { @Override public String toString() { return "Armed service"; } }; } }; }
在创建泛型的时候,可以使代码更简单
例如://参数你不用再后面重新写一遍了,但实际上HaspMap没有这个方法,这里只是举例说明问题 Map<String, List<String> m = HashMap.newInstance();
缺点:
类如果不含有公有的或者受保护的构造器,就不能被子类化
与其他静态方法没有任何区别(不像构造函数那样地位很高)
相关文章推荐
- RAC那些干货——3
- 零基础入门-javaScript学习笔记之变量和作用域
- 关于html语言中的元素标签有哪些是直接闭合的</>,而不是成对出现
- error sass/styles.scss (Line 4: Invalid CSS after "銆€銆€": expected "{", wa s "}")
- Bootstrap模态框(modal)垂直居中
- 零基础入门-javaScript学习笔记之从基本数据类型学起
- jsp指令的include指令
- block,inline和inline-block概念和区别
- Code笔记之:CSS块级元素、内联元素概念
- Code笔记之:CSS+HTML display 属性
- jstl标签<c:forEach>如何获取循环子级元素值
- HTML5 video 和 audio
- json 转list 集合数组
- Knockoutjs 学习系列(一)ko初体验
- js学习笔记(js变量作用域)
- SSH框架网上商城项目第29战之使用JsChart技术显示商品销售报表
- 解决MVC中使用BundleConfig.RegisterBundles引用Css及js文件发布后丢失的问题
- 最强身份证验证
- 基于jQuery下拉选择框插件支持单选多选
- Butterknife使用详解