设计模式 - 简单工厂
实例
图表库
- 开发人员希望开发一套灵活易用的图表库,可以为应用系统提供各种不同外观的图表,如:柱状图,饼图,折线图等。
- 初始设计方案将所有的图表实现代码封装在一个Chart类中,其代码如下:
Chart.java
public class Chart {
/**
* 图表类型
*/
private String type;
/**
* 初始化图表
* @param type
*/
public Chart(String type) {
this.type = type;
if (type.equalsIgnoreCase("bar")) {
System.out.println("初始化柱状图");
} else if (type.equalsIgnoreCase("pie")) {
System.out.println("初始化饼图");
} else if (type.equalsIgnoreCase("line")) {
System.out.println("初始化折线图");
}
}
/**
* 显示图表
* @param type
*/
public void display() {
if (this.type.equalsIgnoreCase("bar")) {
System.out.println("显示柱状图");
} else if (this.type.equalsIgnoreCase("pie")) {
System.out.println("显示饼图");
} else if (this.type.equalsIgnoreCase("line")) {
System.out.println("显示折线图");
}
}
}
- 客户端调用
public class Test {
public static void main(String[] args) {
Chart chart = new Chart("line");
chart.display();
}
}
-
客户端通过调用Chart类的构造函数来创建图表对象,根据参数type的不同可以得到不同类型的图表,再调用displaly()方法来显示相应的图表。
-
缺点如下:
1、Chart类中代码相当冗长,大量的条件语句影响系统的性能
2、Chart类职责过重,违反了单一职责原则
3、当需要增加新类型的图表时需要修改Chart类,违反了开闭原则
4、对象的创建和使用无法分离
简单工厂模式
概念
- 简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,也就是由一个工厂对象决定创建出哪一种产品类的实例
- 简单工厂并不属于23种设计模式,其更像是一种编码风格和习惯
解决方案
Chart.java
/**
* @Description 图表,抽象产品类
*/
public abstract class Chart {
public abstract void display();
}
BarChart.java
/**
* @Description 柱状图
*/
public class BarChart extends Chart {
public BarChart () {
System.out.println("初始化柱状图");
}
@Override
public void display() {
System.out.println("显示柱状图");
}
}
LineChart.java
/**
* @Description 折线图
*/
public class LineChart extends Chart {
public LineChart() {
System.out.println("初始化折线图");
}
@Override
public void display() {
System.out.println("显示折线图");
}
}
PieChart.java
/**
* @Description 饼图
*/
public class PieChart extends Chart {
public PieChart() {
System.out.println("初始化饼图");
}
@Override
public void display() {
System.out.println("显示饼图");
}
}
ChartFactory.java
/**
* @Description 图表工厂
*/
public class ChartFactory {
public static Chart getChart(String type) {
Chart chart = null;
if (type.equalsIgnoreCase("bar")) {
chart = new BarChart();
} else if (type.equalsIgnoreCase("pie")) {
chart = new PieChart();
} else if (type.equalsIgnoreCase("line")) {
chart = new LineChart();
}
return chart;
}
}
Test.java
/**
* @Description 简单工厂测试类
*/
public class Test {
public static void main(String[] args) {
Chart chart = ChartFactory.getChart("line");
chart.display();
}
}
- 测试程序输出如下:
初始化折线图
显示折线图
-
如代码所示,使用工厂类的静态方法创建产品对象,如需更换产品,只需要修改静态工厂方法中的参数即可
-
类图如下:
方案的改进
- 如上代码,在现有模式中增加新的产品时将会修改工厂类源代码,违反开闭原则,可以利用反射从一定程度上满足开闭原则
ChartFactory.java
/**
* @Description 图表工厂
*/
public class ChartFactory {
/**
* 获取图表
* @param c
* @return
*/
public static Chart getChart(Class c) {
Chart chart = null;
try {
chart = (Chart) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return chart;
}
}
Test.java
/**
* @Description 简单工厂测试类
*/
public class Test {
public static void main(String[] args) {
Chart chart = ChartFactory.getChart(BarChart.class);
if (chart == null) {
return;
}
chart.display();
chart = ChartFactory.getChart(PieChart.class);
if (chart == null) {
return;
}
chart.display();
}
}
- 输出:
初始化柱状图
显示柱状图
初始化饼图
显示饼图
总结
- 优点:
1、简单工厂模式实现了对象创建和使用的分离
2、只需要传入一个正确的参数,就可以获取所需要的对象而无需知道其创建细节
3、可以通过反射和引入配置文件在不修改客户端代码的情况下更换和新增产品类
- 缺点:
1、工厂类职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则
- 适用场景:
1、工厂类负责创建的对象比较少
2、应用层只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心
- 源码中使用简单工厂的一些类:
Calendar、DriverManager、LoggerFactory