简单工厂模式并不属于GoF的23种经典模式,但它通常作为其他工厂模式的基础。
定义
定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
结构
Factory(工厂角色)
即工厂类,它是简单工厂模式的核心。负责创建所有产品实例的内部逻辑,它可以直接被外界直接调用,用来创建所需要的产品对象。该类内部提供一个静态方法factoryMethod(),用来创建一个抽象产品类型Product。
Porduct(抽象产品角色)
它是工厂创建的所有对象的父类,封装了各种产品对象的公有方法,使得在工厂类中只需要定义一个通用的工厂方法,因为所有穿点的具体产品都是它的子类对象。
ConcreteProduct(具体产品角色)
它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。
用通俗的语言来讲,我们想吃水果(苹果、橙子、香蕉),我们作为客户。我们不需要知道这些水果它是怎么生产的,我们只需知道我们想购买的水果的名称就可以去超市买来吃,水果的名称相当于就是参数,我们把参数告诉超市,超市就去水果农场去购得该类水果即可。这里的水果,就是抽象的产品,那么这些水果是在水果农场生产出来的,那么这个水果农场就是所谓的工厂,而生产出来的橙子、苹果就是所谓的具体产品。
Spring中也用到了简单工厂模式,比如BeanFactory。根据传入一个唯一的标识来获得bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
应用实例 - 创建各类图表
/**
*
* @ClassName Chart
* @Description 抽象图表接口,充当抽象产品类
* @Author 柳成荫
* @Date 2019年9月21日
* @Version V1.0.0
*/
public interface Chart {
public void display();
}
/**
*
* @ClassName HistogramChart
* @Description 柱状图,充当具体产品类
* @Author 柳成荫
* @Date 2019年9月21日
* @Version V1.0.0
*/
public class HistogramChart implements Chart{
public HistogramChart() {
System.out.println("创建柱状图!");
}
@Override
public void display() {
System.out.println("显示柱状图!");
}
}
/**
*
* @ClassName LineChart
* @Description 折线图类,充当具体产品类
* @Author 柳成荫
* @Date 2019年9月21日
* @Version V1.0.0
*/
public class LineChart implements Chart{
public LineChart() {
System.out.println("创建折线图!");
}
@Override
public void display() {
System.out.println("显示折线图!");
}
}
/**
*
* @ClassName PieChart
* @Description 饼状图类,充当具体产品类
* @Author 柳成荫
* @Date 2019年9月21日
* @Version V1.0.0
*/
public class PieChart implements Chart {
public PieChart() {
System.out.println("创建饼状图!");
}
@Override
public void display() {
System.out.println("显示饼状图!");
}
}
/**
*
* @ClassName ChartFactory
* @Description 图表工厂类
* @Author 柳成荫
* @Date 2019年9月21日
* @Version V1.0.0
*/
public class ChartFactory {
/**
* 静态工厂方法 - 创建具体的图表
* @param type 图表类型 - 柱状图:histogram 饼状图:pie 折线图:line
* @return 具体的图表
*/
public static Chart getChart(String type) {
Chart chart = null;
if("histogram".equalsIgnoreCase(type)) {
chart = new HistogramChart();
System.out.println("初始化设置柱状图");
}else if("pie".equalsIgnoreCase(type)) {
chart = new PieChart();
System.out.println("初始化设置饼状图");
}else if("line".equalsIgnoreCase(type)) {
chart = new LineChart();
System.out.println("初始化折线图");
}else {
System.out.println("没有该类型的图表");
}
return chart;
}
}
/**
*
* @ClassName Client
* @Description 客户端测试类
* @Author 柳成荫
* @Date 2019年9月21日
* @Version V1.0.0
*/
public class Client {
public static void main(String[] args) {
Chart chart = null;
chart = ChartFactory.getChart("pie");
try {
chart.display();
}catch (NullPointerException e) {
System.err.println("类型输入错误,工厂无法创建!");
}
}
}
结果
优点
1.客户端免除了直接创建产品对象的职责,而仅仅“消费”产品,简单工厂模式实现了对象的创建和使用分离。
2.客户端无须知道所创建的产品类的具体类名,只需要知道具体类对应的参数即可,在一定程度上减少了使用者的记忆量。
3.可以通过引入配置文件的方式,不修改任何客户端代码情况下进行更换产品类,一定程度上提高了系统的灵活性。
缺点
1.工厂类集中了所有产品的创建逻辑,职责过重,一旦不能工作,整个系统都要受到影响。
2.会增加系统中类的个数(引入了新的工厂类),增加了系统复杂度和理解难度。
3.系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,产品类型过多的时候就有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
4.使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。