定义
定义一个用于创建对象的接口,让子类决定实例化哪个类。
关键点
- 创建型设计模式之一
- 工厂方法模式又称工厂模式、多态工厂模式和虚拟构造器模式
- 通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象
- 抽象工厂(Factory),为工厂方法模式的核心
- 具体工厂(Concrete Factory),实现了具体的业务逻辑
- 抽象产品(Product),是工厂方法模式所创建的产品的父类
- 具体产品(Concrete Product),为实现抽象产品的某个具体产品对象
使用场景
- 在任何需要生成复杂对象的地方,都可以使用工厂方法模式
- 复杂对象适合使用工厂模式,用new就可以完成创建的对象无需使用工厂模式
场景例子说明
- 抽象产品类
public abstract class Product {
/**
* 抽象产品类的抽象方法
* <br/>
* 由具体的产品类去实现
*/
public abstract void showProduct();
}
- 具体产品类
// 具体产品类A
public class ProductA extends Product {
@Override
public void showProduct() {
System.out.println("我是具体的产品类A");
}
}
// 具体产品类B
public class ProductB extends Product {
@Override
public void showProduct() {
System.out.println("我是具体的产品类B");
}
}
- 抽象工厂类
public abstract class Factory {
/**
* 抽象工厂方法
* <br/>
* 具体生产什么交给子类去做
* @return
*/
public abstract Product createProduct();
}
- 具体工厂类
public class JFactory extends Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
- 测试
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new JFactory();
Product product = factory.createProduct();
product.showProduct();
}
}
//结果
我是具体的产品类A
若是想生产产品类B,则可以将具体工厂类修改如下:
public class JFactory extends Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}
// 结果
我是具体的产品类B
通过反射的方式
在我们具体的工厂中,想要生产那个具体的产品就可以生成具体的产品,但是每次都需要修改具体工厂的内容。如果采用反射的方式,则可以更为简洁地来生产具体产品。
只需要在工厂方法中的参数列表传入一个Class类来决定是哪一个产品类即可。
// 抽象工厂类
public abstract class FS_Factory {
/**
* 抽象工厂方法
* <br/>
* 具体生产什么由子类去实现
* @param clz 产品对象类型
* @param <T>
* @return
*/
public abstract <T extends Product> T createPruduct(Class<T> clz);
}
// 具体工厂类
public class FS_JFactory extends FS_Factory {
@Override
public <T extends Product> T createPruduct(Class<T> clz) {
Product product = null;
try {
product = (Product) Class.forName(clz.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) product;
}
// 测试
public class FactoryTest {
public static void main(String[] args) {
FS_Factory fs_factory = new FS_JFactory();
Product product1 = fs_factory.createPruduct(ProductB.class);
product1.showProduct();
}
}
// 结果
我是具体的产品类B
从上可以知道,通过反射可以需要哪个对象就传入哪个对象的类型即可,这种方式比较简洁、动态。
多工厂方法模式
如果觉得上述反射的方式比较复杂,不易理解,也可以尝试为每个产品单独定义具体的工厂,各司其职。这种方法被称为多工厂方法模式。
public class JFactoryA extends Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
public class JFactoryB extends Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}
简单工厂模式(静态工厂模式)
假设当我们只有一个工厂,那么其实无需抽象工厂类,可以将其简化。同时将简化的工厂里的工厂方法改为静态方法即可。这种方式则被称为简单工厂模式,实际上是工厂方法模式的弱化版本。
// 简单工厂类
public class JD_Factory {
public static Product createProduct() {
return new ProductA();
}
}
// 测试
public class FactoryTest {
public static void main(String[] args) {
Product product2 = JD_Factory.createProduct();
product2.showProduct();
}
}
// 结果
我是具体的产品类A
工厂方法的优缺点
优点:
- 降低了对象间的耦合性
- 对调用者隐藏了产品的生产过程
- 易于拓展
缺点:
- 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销。
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
引用:
《Android源码设计模式解析与实战》
Android设计模式(四)- 工厂方法模式
[Android]三种工厂模式总结。
网友评论