静态工厂方法与构造函数 创建类 区别

前言: 清晰性和简介性是最为重要的
      一个模块的使用者永远也不应该被模块的行为所迷惑(那样就不清晰了),模块要尽可能的小,但又不能太小【术语模块(module):是指任何可重用的软件组件,从单个方法到包含多个包的复杂系统都可以是一个模块】。代码应该被重用,而不是拷贝,模块之间的相依性应该尽可能降低到最小,错误应该尽早被检测出来,理想的情况下是在编译的时刻。


NO.1 考虑用静态工厂方法代替构造函数
      静态工厂方法好处:
      ①构造函数有命名的限制,而静态方法有自己的名字,更加易于理解。
      ②静态工厂方法在每次调用的时候不要求创建一个新的对象。这种做法对于一个要频繁创建相同对象的程序来说,可以极大的提高性能。它使得一个类可以保证是一个singleton;他使非可变类可以保证“不会有两个相等的实例存在”。
      ③静态工厂方法在选择返回类型时有更大的灵活性。使用静态工厂方法,可以通过调用方法时使用不同的参数创建不同类的实例,还可以创建非公有类的对象,这就封装了类的实现细节。
      静态工厂方法坏处:
      ①如果一个类是通过静态工厂方法来取得实例的,并且该类的构造函数都不是公有的或者保护的,那该类就不可能有子类(被继承),子类的构造函数需要首先调用父类的构造函数,因为父类的构造函数是private的,所以即使我们假设继承成功的话,那么子类也根本没有权限去调用父类的私有构造函数,所以是无法被继承的 。
      ②毕竟通过构造函数创建实例还是SUN公司所提倡的,静态工厂方法跟其他的静态方法区别不大,这样创建的实例谁又知道这个静态方法是创建实例呢?弥补的办法就是:静态工厂方法名字使用valueOf或者getInstance.
      总结:静态工厂方法和公有的构造函数都有他们各自的用途,我们要理解他们各自的长处,避免一上来就用构造函数,通常静态工厂更加合适。如果没有其他因素强烈的影响我们的选择,最好还是简单的选择构造函数,毕竟他是语言提供的规范。


NO.2 试用私有构造函数强化singleton属性
      实现singleton的方法有两种:
      方法一:公有的静态成员是一个final域,成员的声明很清楚的表达了这个类是一个singleton。

[c-sharp] view plaincopy
  1. public class Elvis {  
  2.   
  3.     public static final Elvis INSTANCE = new Elvis();  
  4.   
  5.     private Elvis() { }  
  6.   
  7.     public void leaveTheBuilding() {  
  8.   
  9.         System.out.println("Who a baby, I'm outta here!");  
  10.   
  11.     }  
  12.   
  13.     // This code would normally appear outside the class!  
  14.   
  15.     public static void main(String[] args) {  
  16.   
  17.         Elvis elvis = Elvis.INSTANCE;  
  18.   
  19.         elvis.leaveTheBuilding();  
  20.   
  21.     }  
  22.   
  23.   }  

      
      方法二:提供一个公有的静态方法,而不是公有的静态final域。该方式提供了更大的灵活性,在不改变API的前提下,可以把该类改成singleton或者非singleton的。

  1. public class Elvis {  
  2.   
  3.     private static final Elvis INSTANCE = new Elvis();  
  4.   
  5.     private Elvis() { }  
  6.   
  7.     public static Elvis getInstance() { return INSTANCE; }  
  8.   
  9.     public void leaveTheBuilding() {  
  10.   
  11.         System.out.println("Who  a baby, I'm outta here!");  
  12.   
  13.     }  
  14.   
  15.     // This code would normally appear outside the class!  
  16.     public static void main(String[] args) {  
  17.   
  18.         Elvis elvis = Elvis.getInstance();  
  19.   
  20.         elvis.leaveTheBuilding();  
  21.     }  
  22.   }  

 

      一般来说,第一种方法效率稍微高一些,然后,采用第一种方法实现singleton后,就没有改变的余地了,当你想把该类改成非singleton,显然是不行的了。所以,除非确实确定该类是一个singleton,那就用第一个方法吧。用第2种方法的时候,假如该类实现了serializable接口,那应该重写(override)readResolve()方法,否则再反序列化的时候是会产生一个新的实例,这与singleton相违背了!



NO.3 通过私有的构造函数强化不可实例化的能力

      在面向对象程序设计中,假如存在太多只有静态属性和静态方法的类;那么,面向对象的思想可能在这会损失殆尽。但是,并不能说面向对象的程序中就不应该出现只有静态属性和静态方法的类,相反,有时候我们还必须写这样的类作为工具类。这样的类怎么实现呢?有人可能会把该类定义成抽象类(Abstract class),的确,抽象类是不可以实例化的,但是别忘了还有继承,继承了抽象类的子类在实例化时候,默认是会先调用父类无参数的构造函数的(super();),这时候,父类不是也被实例化了嘛?其实我们可以这样做,把该类的构造函数定义为私有的(private),而类的内部又不调用该构造函数的话,就成功了。这样带来的后果就是该类成了 final的,不可能再被任何类继承了,要被继承,得提供一个公有(public)的或者保护(protect)的构造函数,这样才能被子类调用。
posted on 2014-06-06 02:58  xflash  阅读(818)  评论(0编辑  收藏  举报