定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂模式使一个类的实例化延迟到其子类
举个栗子:
定义一个抽象产品类Product负责定义产品的共性,实现对事物的抽象定义;AbstractCreator为抽象工厂,具体如何创建由具体的实现工厂ContractorCreator完成。
//抽象产品类
public abstract class Product {
//产品类公共方法
public void method1(){
//处理业务逻辑
}
//抽象方法
public abstract void method2();
}
//具体产品类A
public class ProductA extends Product {
@Override
public void method2() {}
}
//具体产品类B
public class ProductB extends Product {
@Override
public void method2() {}
}
// 抽象工厂类
public abstract class AbstractCreator {
/**
* 创建一个产品对象,输入参数可以自行设置
* 同常是String、Enum、Class等,也可为空
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
//具体的实现工厂类
public class ProductCreator extends AbstractCreator {
@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;
}
}
//场景类
public class Client {
public static void main(String[] args) {
AbstractCreator creator = new ProductCreator();
creator.createProduct(ProductA.class);
creator.createProduct(ProductB.class);
//...业务处理
}
}
优点
* 结构清晰,易于扩展。在增加产品类的情况下,只需要增加具体的产品类,或者适当的修改具体的工厂类或扩展一个工厂类。
* 屏蔽产品类。产品类如何变化,调用者不需要关心,只需要关心产品的接口。
* 解耦合。高层模块只需要知道产品的抽象类,其他的实现类都不用关心,符合迪米特法则,也符合依赖倒置原则和里氏替换原则。
扩展
简单工厂模式
去掉抽象工厂AbstractCreator,修改具体的实现工厂ContractorCreator中的方法为static,简化了类的创建过程。也称为静态工厂模式,缺点是工厂类的扩展比较困难
//具体实现工厂类
public class ProductCreator {
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 class Client {
public static void main(String[] args) {
ProductA productA = ProductCreator.createProduct(ProductA.class);
ProductB productB = ProductCreator.createProduct(ProductB.class);
productA.method1();
productB.method1();
}
}
升级为多个工厂类
当项目比较复杂时,比如一个产品类有许多个具体的产品实现类,每个实现类的初始化方法都不同,可以考虑为每一个产品定义一个创建者,由调用者自己去选择与哪个工厂方法关联。
// 抽象工厂类
//抽象方法之后不再需要参数,因为每个产品工厂只负责创建自己的产品对象
public abstract class AbstractCreator {
public abstract Product createProduct();
}
//产品子工厂类
public class ProductACreator extends AbstractCreator {
@Override
public Product createProduct() {
return new ProductA();
}
}
替代单例模式
单例工厂可以通过反射创建一个单例类
//单例类
public class Singleton {
private Singleton(){
}
public void doSomething(){
//相关业务方法
System.out.println("业务方法被调用");
}
}
//单例工厂类
public class SingletonFactory {
private static Singleton singleton;
static {
try {
Class clazz = Class.forName(Singleton.class.getName());
//获得无参构造
Constructor constructor = clazz.getDeclaredConstructor();
//设置无参构造是可访问的
constructor.setAccessible(true);
//生成对象
singleton = (Singleton) constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Singleton getSingleton(){
return singleton;
}
}
//场景类
public class Client {
public static void main(String[] args) {
Singleton singleton = SingletonFactory.getSingleton();
singleton.doSomething();
}
}
延迟初始化
一个对象被消费完后,并不立即释放,工厂类保持其初始状态,等待再次被使用。
//延迟加载的工厂类
public class ProductFactory {
//pMap模拟缓存
private static final Map<String, Product> pMap = new HashMap();
public static synchronized Product createProduct(String type) throws Exception {
Product product = null;
if (pMap.containsKey(type)) {
product = pMap.get(type);
} else {
if ("ProductA".equals(type)) {
product = new ProductA();
} else ("ProductB".equals(type)) {
product = new ProductB();
}
//放入缓存
pMap.put(type, product);
}
return product;
}
}
延迟加载是可以扩展的,比如限制一个产品类的最大实例化数量,可以通过判断map中的已有对象数量实现。例如JDBC中连接数据库最大连接数。