本文属于系列文章《设计模式》,附上文集链接
工厂模式定义
- 定义一个创建对象的接口,由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类
- 作用:没使用工厂的话,我们要创造对象使用new,工厂方法就是帮我们负责创建需要的对象。
- 工厂模式是创建类模式。
实现
先看一下没用到工厂类的场景,我们需要AProduct和BProduct
//产品类接口
public interface IProduct {
public void say();
}
// A产品类
public class AProduct implements IProduct {
@Override
public void say() {
System.out.println("我是A产品");
}
}
//B产品类
public class BProduct implements IProduct {
@Override
public void say() {
System.out.println("我是B产品");
}
}
//场景类
public class Client {
public static void main(String[] args) {
IProduct aProduct = new AProduct();
aProduct.say();
IProduct bProduct = new BProduct();
bProduct.say();
}
}
结果:
我是A产品
我是B产品
完美运行,但是这个有什么问题呢?试想一下,假设以后改需求,需要在生产产品的时候传入生产批次,怎么传?构造函数或者setter都可以,但是都有一个问题,就是我们在改了产品类的时候,还得改正在使用它的地方,这个耦合其实可以解的,用的就是工厂方法。
// 抽象工厂类
public abstract class AbstractFactory {
public abstract <T extends IProduct> T getProduct(Class<T> clazz) ;
}
// 具体工厂类
public class ConcreteFactory extends AbstractFactory{
@Override
public <T extends IProduct> T getProduct(Class<T> clazz) {
T product = null;
try {
product = (T) Class.forName(clazz.getName()).newInstance();
} catch (Exception e) {
}
return product;
}
}
// 产品类不变
// 场景类
public class Client {
public static void main(String[] args) {
ConcreteFactory factory = new ConcreteFactory();
AProduct aproduct = factory.getProduct(AProduct.class);
aproduct.say();
BProduct bProduct = factory.getProduct(BProduct.class);
bProduct.say();
}
}
结果:
我是A产品
我是B产品
- 分析下上面的代码,定义了一个抽象工厂类,工厂里面有一个方法,接收参数是继承产品类接口的类的类属性,确保工厂生产出来必定是继承自IProduct的对象。为什么要用泛型?因为你会发现,不用泛型的话,接收的参数不知道该怎么定义,直接用IProduct的class属性的话,在使用ConcreteFactory传参的时候是不能传实现IProduct接口的类的class属性的。
- 然后结果不变,但是可以发现,依赖关系改变了,没改动代码之前,调用者(场景类)依赖于产品类,只要产品类有改动,都有可能对调用者造成影响。而使用工厂模式后,调用者对产品类的依赖变成了对工厂类的依赖,无论产品类如何变化,调用者都不需要关心,只需要工厂类能够正确返回对象即可,实现了解耦。
以上就是工厂模式。