定义
定义一个用于创建对象的接口,让子类决定实例化哪个类
使用场景
在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复合对象适合使用工厂模式,用new就可以完成创建的对象无需使用工厂模式。
关键点
一个抽象工厂—定义创建对象的接口
抽象工厂的实现类—可以是一个实现或多个实现,用于生产需要的具体对象
一个抽象产品—工厂方法模式所创建的产品的父类
抽象产品的实现类—需要被创建的具体产品
实现
/**
* 抽象工厂类—定义生产抽象对象的接口
*/
public abstract class AbstractFactory {
public abstract AbstractProduct createProduct();
}
/**
* 抽象产品类—工厂模式的抽象接口需要创建返回的类型
*/
public abstract class AbstractProduct {
/**
* 抽象产品内的抽象方法
*/
public abstract void showProductName();
}
/**
* 抽象工厂的实现类—创建具体需要的产品
*/
public class ProductFactory extends AbstractFactory {
@Override
public AbstractProduct createProduct() {
//根据需要创建具体的产品,这里我们创建产品A
return new ProductA();
}
}
/**
* 具体的产品A
*/
public class ProductA extends AbstractProduct {
@Override
public void showProductName() {
Log.i("Product:", "A");
}
}
/**
* 具体的产品B
*/
public class ProductB extends AbstractProduct {
@Override
public void showProductName() {
Log.i("Product:", "B");
}
}
使用
AbstractFactory factory = new ProductFactory();
AbstractProduct product = factory.createProduct();
product.showProductName();
输出
01-01 00:05:58.728 2840-2840/com.example.admin.singleinstancedemo I/Product:: A
当然我们也可以在具体创建产品的工厂类里面创建B产品。上面这种方式是最常见的需要哪一个产品就生产哪一个。除此之外,我们还可以利用反射的方式去更加简洁的生产具体的产品对象,修改抽象工厂类和具体工厂类如下:
/**
* 抽象接口类—定义生产抽象对象的接口
*/
public abstract class AbstractFactory {
public abstract <T extends AbstractProduct> T createProduct(Class<T> clz);
}
/**
* 抽象工厂的实现类—创建具体需要的产品
*/
public class ProductFactory extends AbstractFactory {
@Override
public <T extends AbstractProduct> T createProduct(Class<T> clz) {
AbstractProduct product = null;
try {
product = (AbstractProduct) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) product;
}
}
使用
AbstractFactory factory = new ProductFactory();
AbstractProduct product = factory.createProduct(ProductB.class);
product.showProductName();
输出结果
01-01 00:26:19.950 16938-16938/com.example.admin.singleinstancedemo I/Product:: B
需要哪一个类的对象就传入哪一个类的类型即可,这种方式比较简介、动态,当然我们也可以为每个具体的产品定义一个具体的工厂类,比如在第一种方式基础上多增加一个专门用于生产ProductB的工厂
/**
* 抽象工厂的实现类—创建具体需要的产品B
*/
public class ProductFactoryB extends AbstractFactory {
@Override
public AbstractProduct createProduct() {
return new ProductB();
}
}
然后需要A的时候使用ProductFactory工厂创建A实例,需要B的时候使用ProductFactoryB工厂创建B实例,各司其职。这样拥有多个工厂的方式我们称为多工厂方法模式。
当只有一个工厂的时候,我们还是为工厂提供了一个抽象类,是否可以将其简化掉呢?当然是可以的:
/**
* 直接提供静态方法—向外创建对象
*/
public class ProductFactory {
public static AbstractProduct createProduct(){
return new ProductA();
}
}
像这样的方式又称之为简单工厂模式或静态工厂模式
小结
工厂方法模式降低了对象之间的耦合度,依赖于抽象的架构,将实例化的任务交由子类去完成,有非常好的扩展性,符合软件设计原则。
优点:
1.在工厂方法中,用户只需要知道所要产品的具体工厂,无须关系具体的创建过程,甚至不需要具体产品类的类名。
2.在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
缺点:
1.每次增加一个产品时,都需要增加一个具体类和对象实现工厂,是的系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。