一、需求背景
Sunny 公司 CRM 系统需要展示多种统计图表,现有饼图 (PieChart)、柱状图 (BarChart)。原有设计中ChartDisplay通过传入类型字符串,使用 if 判断来创建对应图表对象、调用展示方法。这种写法新增折线图、雷达图等新图表时,需要修改ChartDisplay内部代码,违背开闭原则(对扩展开放、对修改关闭)。
本文使用抽象 + 多态的思路重构代码,满足开闭设计思想。
二、原有方案缺陷分析
原始设计:ChartDisplay 的 display (String type) 依靠字符串区分图表类型,内部分支判断实例化不同图表。
1.新增任何新图表,必须修改 ChartDisplay 的源代码,改动原有稳定代码容易引入 bug;
2.分支条件越来越多,代码臃肿,维护难度大;
3.不符合开闭原则:扩展需要修改原有类。
三、重构思路(遵循开闭原则)
1.抽象顶层图表接口 / 抽象类 Chart,统一规范display()展示方法,所有具体图表实现该抽象;
2.PieChart、BarChart 以及后续新增的 LineChart 等都实现 Chart,各自重写 display ();
3.修改 ChartDisplay,不再使用字符串判断,依赖抽象 Chart,通过依赖注入传入具体图表对象;
4.后续新增图表只需要新建实现类,完全不用改动 ChartDisplay 源码,实现对扩展开放、修改关闭。
四、代码实现
// 抽象图表接口,定义统一展示规范
public interface Chart {
void display();
}
// 饼图实现
public class PieChart implements Chart{
@Override
public void display() {
System.out.println("展示饼状图数据");
}
}
// 柱状图实现
public class BarChart implements Chart{
@Override
public void display() {
System.out.println("展示柱状图数据");
}
}
public class ChartDisplay {
// 依赖抽象,不依赖具体实现类
public void display(Chart chart){
// 多态自动调用对应图表的display,无if判断
chart.display();
}
}
public class Client {
public static void main(String[] args) {
ChartDisplay display = new ChartDisplay();
// 使用饼图
display.display(new PieChart());
// 使用柱状图
display.display(new BarChart());
}
}
五、扩展新增图表(验证开闭原则)
需求新增折线图 LineChart,无需修改 ChartDisplay 任何代码,只新增实现类即可:
// 新增折线图,扩展功能,不改原有代码
public class LineChart implements Chart{
@Override
public void display() {
System.out.println("展示折线图数据");
}
}
客户端新增调用:
display.display(new LineChart());
六、总结
1.开闭原则核心:面向抽象编程,而非面向具体实现编程;
2.原有 if/switch 分支选型的写法是典型违反开闭的设计,适合用多态 + 抽象重构;
3.后续任何新图表都只需要新增 Chart 实现类,原有 ChartDisplay 稳定不变,降低代码维护风险。
