只列举常用的几个
一,单例
一个普通类可以有自己的静态工厂方法, 从而使类自己遵守单例模式.即这个类只能实例化一次,外部也只能通过静态工厂方法获取到这个类的唯一实例.示例如下:
/**
* 通过静态工厂方法的方式,将一个类设计为单例
*/
public class ClassA {
private static final ClassA a = new ClassA(); //用静态final域引用ClassA的唯一实例
//构造方法要设为私有
private ClassA(){
}
public static ClassA getInstance(){ //使用静态工厂方法返回唯一实例的引用
return a;
}
}
需要注意的是,有两种特殊情形下,上面设计单例的方式会有问题:
1,通过反射机制,可以调用私有的构造器.
解决办法: 可以在私有构造函数中通过设计一个类的静态计数器字段,判断私有构造函数是否第一次被调用,如果不是,那么可以抛出异常.
2,可序列化的类每次反序列化时都会创建一个新的实例.
解决办法:可以在类中加入private Object readResolve()方法返回静态final域引用的唯一实例来避免重复创建对象.
扩展: 实现单例的最佳方法是编写一个包含单个元素的枚举类型.
参见文章: 《浅谈java中单例的设计》
二,在工厂类中,用于定制同一接口的不同实现的实例,或者是同一父类的不同子类的实例.示例如下:
class People {
}
class Father extends People {
}
class SonA extends Father {
}
class SonB extends Father {
}
public class PeopleFactory {
/**
* 使用静态工厂方法,通过传入参数定制不同的People实例
* @param id
* @return
*/
public static People getPeopleInstance(char id) {
switch (id) {
case 'F':
return new Father();
case 'A':
return new SonA();
case 'B':
return new SonB();
default:
return new People();
}
}
}
三,灵活的静态工厂方法,也构成了"服务提供者框架"的基础.
就拿JDBC举例,JDBC是java编程与数据库交互的接口,它仅是一种规范,不同的数据库厂商,如oracle,mysql等等,根据这个规范的JDBC接口,写出针对自己数据库的JDBC实现,所以在java编程与数据库交互时,要根据数据库的不同导入JDBC不同的实现的 jar 包,才能正确地与数据库打交道.
以使用JDBC连接MySql为例:
Class.forName("com.mysql.jdbc.Driver");
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","root","root");
在这里,Driver是JDBC定义的
服务提供者接口,
com.mysql.jdbc.Driver是MySql提供的实现类.在使用
静态工厂方法Class.forName()加载
com.mysql.jdbc.Driver类时,Driver类会创建自己的实例并
向 DriverManager 注册实例;而Connection是
服务接口,通过调用
静态工厂方法getConnection()以及传入的参数获取Connection服务接口的实现的实例.而这个实现是MySql厂商提供的,DriverManager会通方法的传入参数配对已注册的服务提供者,从而找到对应的服务提供者提供的服务(Connection实现).
可以以一种简洁的方式去理解静态工厂方法在这里充当的角色.如下面代码所示,理解时可把JDBC接口规范比作Car,把Audi(奥迪)比作oracle的JDBC实现,把Benz(奔驰)比作mysql的JDBC实现,以此类比......我与数据库打交道,是通过JDBC接口,同样,我与车打交道,是通过Car接口;真正与数据库打交道时,比如跟oracle,那么就要加载oracle的JDBC实现;同样,真正与车打交道时,比如Audi(奥迪),那么就要加载Audi这个车的实现,如下代码所示,只要把Audi的类全名当作参数传给静态工厂方法,那么就能获取到实打实的Car实例了,而且这个Car实例是和Audi打交道的,与Benz(奔驰)或者(BMW)宝马没有关系.
如下面代码所示:
interface Car {
public void printName();
}
class Audi implements Car {
@Override
public void printName() {
System.out.println("奥迪");
}
}
class Benz implements Car {
@Override
public void printName() {
System.out.println("奔驰");
}
}
class BMW implements Car {
@Override
public void printName() {
System.out.println("宝马");
}
}
public class Factory {
/**
* 通过静态工厂方法,传入实现Car接口的实现类的全名,获取该实现类的实例
* @param className
* @return
* @throws Exception
*/
public static Car getCarInstance(String className) throws Exception {
Class cl = Class.forName(className);
Car car = (Car) cl.newInstance();
return car;
}
public static void main(String [] args) throws Exception{
Car car = getCarInstance("Audi");//把Audi的类全名当作参数传给静态工厂方法
car.printName();
}
}