定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
通用类图:
代码如下:
public abstract class Product {
public void method1(){
System.out.println("method1 invoked");
}
public abstract void method2();
}
public class ConcreteProduct1 extends Product {
@Override
public void method2() {
System.out.println("product1 method2 invoked");
}
}
public abstract class Creator {
/**
* 创建一个产品对象,其输入参数类型可以自行设置
* 通常为String、Enum、Class等,当然也可以为空
* @param c
* @return
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
public class ConcreteCreator extends Creator {
@Override
public <T extends Product> T createProduct(Class<T> c) {
Product product=null;
try {
product=(Product)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T)product;
}
}
工厂方法模式的优点:
1、良好的封装性,代码结构清晰
2、扩展性很好
3、屏蔽产品类
工厂模式的扩展:
1、缩小为简单工厂模式
即一个模块仅需要一个工厂类,没有必要使用抽象类,使用静态的方法就可以了。代码如下:
public class SimpleCreator {
public static <T extends Product> T createProduct(Class<T> c){
Product product=null;
try {
product=(Product)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T)product;
}
}
简单工厂模式的缺点是工厂类的扩展比较困难,不符合开闭原则,但是非常实用。
即针对每一种产品,单独创建一个工厂类,而不是混合在一起,根据传入参数的类型判断要产生哪种产品,这样的方法更符合单一职责原则,类图如下:
源代码如下:
public abstract class Creator {
public abstract Product createProduct();
}
public class Product1Creator extends Creator {
@Override
public Product createProduct() {
return new ConcreteProduct1();
}
}
public class Product2Creator extends Creator {
@Override
public Product createProduct() {
return new ConcreteProduct2();
}
}
多工厂类应用在每个实现类的初始化都不一样的情况下,而这种情况更为普遍,但是这样就增加了维护的难度,一种产品就有一个对应的工厂类。当然,也可以将各个子工厂类进行封装,向外提供统一的接口,这样就避免了代码混乱。
3、替代单例模式
前面所说的单例模式有一定的缺点,比如说对测试不利,因为它没有接口,不能用来mock的方法虚拟一个对象。我们可以用工厂方法模式的方法,来写一个单例模式的例子,抓住主要矛盾:单例模式要求在内存中,只存在一个实例。其类图如下:
代码如下:
public class Singleton {
//定义成私有的构造函数,防止被外部实例化
private Singleton(){
System.out.println("Singleton is created");
}
public void doSomething(){
System.out.println("do something...");
}
}
public class SingletonFactory {
private static Singleton singleton;
static{
try{
Class clss=Class.forName(Singleton.class.getName());
//获得无参构造函数
Constructor constructor=clss.getDeclaredConstructor();
//设置无参构造函数是可访问的
constructor.setAccessible(true);
//产生一个实例
singleton=(Singleton)constructor.newInstance();
}catch(Exception e){
e.printStackTrace();
}
}
public static Singleton getSingleton(){
return singleton;
}
}
延迟初始化,即一个对象被消费完后,并不立即释放,工厂类保存其初始状态,等待再次被使用,通用类图如下:
延迟工厂类代码如下:
public class LazyCreator {
private static final Map<String,Product> map=new HashMap<String,Product>();
public static synchronized Product createProduct(String key){
Product product=null;
if(map.containsKey(key)){
return map.get(key);
}
else{
if(key.equals("Product1")){
product=new ConcreteProduct1();
}
else if(key.equals("Product2")){
product=new ConcreteProduct2();
}
map.put(key, product);
}
return product;
}
}