工厂方法模式使用的频率非常高,在我们日常的开发中总能见到它的身影。其定义为:Define an interface for creating an object,but let subclasses deide which class to instantiate.Factory Method lets a class defer instantitaion to subclasses.(定义一二个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使用一个类的实例化延迟到其子类。)
下面笔者提供一个比较实用的通用源码。
Product.java 抽象产品类,具体的产品类可以有多个,都集成于抽象产品类
package com.jaynol.designpatterns.factorymethod;
public abstract class Product {
/**
* 产品类公共方法
* 可以考虑增加final关键字,防止子类重写,因为重写后会破坏封装性
*/
public void method1(){
//业务逻辑实现
}
//抽象方法,供子类做个性化扩展
public abstract void method2();
}
ConcreteProduct1.java 具体产品类
package com.jaynol.designpatterns.factorymethod;
public class ConcreteProduct1 extends Product{
@Override
public void method2() {
//业务逻辑实现
System.out.println("ConcreteProduct1 业务逻辑");
}
}
ConcreteProduct2.java 具体产品类
package com.jaynol.designpatterns.factorymethod;
public class ConcreteProduct2 extends Product{
@Override
public void method2() {
//业务逻辑实现
System.out.println("ConcreteProduct2 业务逻辑");
}
}
Creator.java 抽象工厂
package com.jaynol.designpatterns.factorymethod;
public abstract class Creator {
/**
* 创建一个产品对象,其输入参数类型可以自行设置
* 通常为String,Enum,Class等,当然也可以为空
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
package com.jaynol.designpatterns.factorymethod;
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){
//异常处理
}
return (T)product;
}
}
Client.java 场景类
package com.jaynol.designpatterns.factorymethod;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
//创建一个产Product的工厂
Creator creator = new ConcreteCreator();
//生产concreteProduct1这个类产品
ConcreteProduct1 concreteProduct1 = creator.createProduct(ConcreteProduct1.class);
concreteProduct1.method2();
//生产concreteProduct2这个类产品
ConcreteProduct2 concreteProduct2 = creator.createProduct(ConcreteProduct2.class);
concreteProduct2.method2();
}
}
工厂方法模式的优点:
1.良好的封装性,代码结构清晰。一个对象的创建是有条件约束的,如一个调用者需要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,降低模块间的耦合。
2.工厂方法模式的扩展性非常优秀。在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成“拥抱变化”。例如在我们的例子中,需要增加一个ConcreteProduct3产品,只需要增加一个ConcreteProduct3类,工厂类都不用任何修改就能完成系统的扩展。
3.屏蔽产品类。这一特点非常重要,产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不会发生变化。因为产品类的实例化工作是由工厂类负责的。一个产品的对象具体由那个一个产品生成是由工厂类决定的。在数据库开发中,大家因应该能够深刻体会到工厂方法模式的好处:如果使用JDBC连接数据库,数据库从MySQL切换到Oracle,需要改动的地方就是切换一下驱动名称(前提条件是SQL语句是标准语句),其他的都不需要修改,这是工厂方法模式灵活性的一个直接案例。
4.工厂方法模式是典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不用关心,符合迪米特法则,则我不需要的就不要去交流;也复核依赖倒置原则,只依赖产品的抽象;当然也复核里氏替换原则,使用产品子类替换产品父类,没问题!
工厂方法模式扩展:
1.缩小为简单工厂模式
我们这样考虑一个问题:一个模块仅需要一个工厂类,没有必要把它生产出来,使用静态的方法就可以了,根据这一要求,笔者把上面例子中的Creator修改一下,代码如下:
package com.jaynol.designpatterns.factorymethod;
public class SimpleFactoryMethod {
public static <T extends Product> T createProduct(Class<T> c) {
Product product = null;
try{
product = (Product) Class.forName(c.getName()).newInstance();
}
catch(Exception e){
//异常处理
}
return (T)product;
}
}
通过这样的修改,场景类修改如下:
package com.jaynol.designpatterns.factorymethod;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
//生产concreteProduct1这个类产品
ConcreteProduct1 concreteProduct1 = SimpleFactoryMethod.createProduct(ConcreteProduct1.class);
concreteProduct1.method2();
//生产concreteProduct2这个类产品
ConcreteProduct2 concreteProduct2 = SimpleFactoryMethod.createProduct(ConcreteProduct2.class);
concreteProduct2.method2();
}
}
2.升级为多个工厂
当我们做一个比较复杂的项目时,经常会遇到初始化一个对象是一件很复杂的事情,并且需要针对不同的产品的生产过程做定制,如果把这些逻辑都放在一个工厂里代码结构就不清晰了。例如,上面例子中的两个产品ConcreteProduct1和ConcreteProduct2,需要在生产ConcreteProduct1时给它初始化名字为ConcreteProduct1而ConcreteProduct2则需要初始化名字为ConcreteProduct2,把这段逻辑通过if eslse写在一个Creator里就不易于扩展和维护了。为了满足这种需求,需要把上面的工厂方法模式升级为多个工厂的方式,代码如下:
抽象工厂:
package com.jaynol.designpatterns.factorymethod;
public abstract class AbstractCreator {
protected abstract Product createProduct();
}
生产ConcreteProduct1的工厂:
package com.jaynol.designpatterns.factorymethod;
public class ConcreteProduct1Creator extends AbstractCreator{
@Override
protected Product createProduct() {
/**
* 可在此处实现初始化的逻辑
*/
return new ConcreteProduct1();
}
}
生产ConcreteProduct2的工厂:
package com.jaynol.designpatterns.factorymethod;
public class ConcreteProduct2Creator extends AbstractCreator{
@Override
protected Product createProduct() {
/**
* 可在此处实现初始化的逻辑
*/
return new ConcreteProduct2();
}
}
场景类如下:
package com.jaynol.designpatterns.factorymethod;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
//生产concreteProduct1这个类产品
Product concreteProduct1 = (new ConcreteProduct1Creator()).createProduct();
concreteProduct1.method2();
//生产concreteProduct2这个类产品
Product concreteProduct2 = (new ConcreteProduct2Creator()).createProduct();
concreteProduct2.method2();
}
}