【重构】使用简单工厂模式重构Switch语句
2016-12-23 12:29
316 查看
Code Smell:Switch Statements
Switch语句的问题在于,一旦有新case出现,Switch语句块就要加上这条case。
如果Switch语句块很多且散布在不同的地方,找到并修改它们将是非常恐怖的事。
下面这个例子是,根据枚举中employee的角色,
GetDescription(EmployeeType empType)方法给出employee的职位描述;
PayAmount(EmployeeType empType)方法给出employee的薪酬。
如果这个时候我在枚举中添加另一个角色:consultant。
那么我就要找到上面两个方法,把case consultant的判断语句加到原来的switch语句中。
而简单工厂模式重构的意义在于:不用再去找涉及新角色的switch语句,把角色应有的属性和方法直接写在该角色所在的类中。
多态是面向对象编程的精髓之一,我们来回顾多态的要点:
1.接口/抽象类的引用变量可以引用实现类的对象
2.父类的引用变量可以引用子类的对象
3.实现类需要重写抽象方法
基于多态的理念,我们
第一步:把case中的角色抽象成继承了(实现了)统一抽象类(接口)的子类。
第二步:子类实现各自的抽象方法
第三步:工厂根据定制,按需创建子类的对象。
STEP1
把Switch语句中的每个case抽取出来:
class Engineer
class Salesman
class Manager
STEP2
然后把他们共有的部分抽象为一个抽象类或者接口:
abstract class Employee
STEP3
工厂接收抽象类或接口的引用变量,再根据引用变量的类型按条件new出具体的子类。工厂可以是一个单独的类,也可以是放在上面的抽象类中。
简单工厂模式的缺陷:
1.甲方必须知道工厂能产出什么,否则工厂要抛出异常。
2.新增了case后,虽然不用再去找散落各处的switch语句,但是工厂中的switch语句还是要跟着改的,违反了开闭原则。
Switch语句的问题在于,一旦有新case出现,Switch语句块就要加上这条case。
如果Switch语句块很多且散布在不同的地方,找到并修改它们将是非常恐怖的事。
下面这个例子是,根据枚举中employee的角色,
GetDescription(EmployeeType empType)方法给出employee的职位描述;
PayAmount(EmployeeType empType)方法给出employee的薪酬。
如果这个时候我在枚举中添加另一个角色:consultant。
那么我就要找到上面两个方法,把case consultant的判断语句加到原来的switch语句中。
而简单工厂模式重构的意义在于:不用再去找涉及新角色的switch语句,把角色应有的属性和方法直接写在该角色所在的类中。
package refraction.swith; public class BeforeRefraction { enum EmployeeType{ ENGINEER,SALESMAN,MANAGER; } public static int m_basicSalary; public static int m_commission; /** * * switch语句接收枚举类型,判断输出相应的薪资算法 * @param empType Employee type in enum * @return Payment of each type */ public int PayAmount(EmployeeType empType) throws Exception { switch (empType) { case ENGINEER: return m_basicSalary; case SALESMAN: return m_basicSalary + m_commission; case MANAGER: return 2 * m_basicSalary; default: throw new Exception("no such employee type!"); } } /** * switch再来一遍,接收枚举类型,判断输出相应的职位描述 * * @param empType Employee type in enum * @return Description of each type */ public String GetDescription(EmployeeType empType) throws Exception { switch (empType) { case ENGINEER: return "Coding, Debug, Optimization"; case SALESMAN: return "Getting contracts"; case MANAGER: return "Analysis, Scheduling, Reporting"; default: throw new Exception("no such employee type!"); } } }
多态是面向对象编程的精髓之一,我们来回顾多态的要点:
1.接口/抽象类的引用变量可以引用实现类的对象
2.父类的引用变量可以引用子类的对象
3.实现类需要重写抽象方法
基于多态的理念,我们
第一步:把case中的角色抽象成继承了(实现了)统一抽象类(接口)的子类。
第二步:子类实现各自的抽象方法
第三步:工厂根据定制,按需创建子类的对象。
STEP1
把Switch语句中的每个case抽取出来:
class Engineer
class Salesman
class Manager
STEP2
然后把他们共有的部分抽象为一个抽象类或者接口:
abstract class Employee
STEP3
工厂接收抽象类或接口的引用变量,再根据引用变量的类型按条件new出具体的子类。工厂可以是一个单独的类,也可以是放在上面的抽象类中。
package refraction.swith; public class AfterRefraction { public static void main(String[] args) { Employee employee = null; try { employee = Factory.getEmployee(EmployeeType.ENGINEER); } catch (Exception e) { e.printStackTrace(); } employee.getDescription(); System.out.println("Salary:"+employee.PayAmount()); } } enum EmployeeType{ ENGINEER,SALESMAN,MANAGER; } abstract class Employee{ public static int m_basicSalary; public static int m_commission; /* * 工厂方法也可以放在这里,仍然是一个静态方法 */ public abstract String getDescription(); public abstract int PayAmount(); } //把Switch语句中的每个case抽取出来,然后把他们共有的部分抽象为一个抽象类或者 class Engineer extends Employee{ @Override public String getDescription() { return "Coding, Debug, Optimization"; } @Override public int PayAmount() { return m_basicSalary; } } class Salesman extends Employee{ @Override public String getDescription() { return "Getting contracts"; } @Override public int PayAmount() { return m_basicSalary + m_commission; } } class Manager extends Employee{ @Override public String getDescription() { return "Analysis, Scheduling, Reporting"; } @Override public int PayAmount() { return m_basicSalary *2; } } /** * * 工厂类,这里只有一个静态方法 * 工厂类只做一件事:按条件new对象 * 这样一来,我们在main方法中就不用new不同的employee对象了 */ class Factory{ public static Employee getEmployee(EmployeeType employee) throws Exception{ switch(employee){ case ENGINEER: return new Engineer(); case SALESMAN: return new Salesman(); case MANAGER: return new Manager(); default: throw new Exception("no such employee type!"); } } }
简单工厂模式的缺陷:
1.甲方必须知道工厂能产出什么,否则工厂要抛出异常。
2.新增了case后,虽然不用再去找散落各处的switch语句,但是工厂中的switch语句还是要跟着改的,违反了开闭原则。
相关文章推荐
- 抽象工厂模式:简单工厂模式、工厂方法模式对比;在工厂方法模式中使用反射创建对象实例
- 机房重构利用策略模式+简单工厂实现消费金额的计算
- 设计模式笔记1 - 简单工厂 和 工厂模式理解以及使用
- java语言基础-switch语句的简单使用
- Java技术_每天掌握一种设计模式(003)_使用场景及简单实例(创建型:工厂方法)
- 重构:switch语句改成策略模式还是状态模式
- 抽象工厂模式第二步-使用简单工厂模式
- 实例解析C#设计模式编程中简单工厂模式的使用
- 工厂模式之消除switch/case语句
- 机房重构利用策略模式+简单工厂实现消费金额的计算
- 解析XML,将数据显示在treeview上,使用简单工厂模式
- 外观模式-facade实现interface的方式(简单工厂+facade组合使用)
- Java反射机制(五):使用反射增强简单工厂设计模式
- Ruby中使用设计模式中的简单工厂模式和工厂方法模式
- 设计模式(1)-使用简单工厂优化代码
- NDatabase 入门,简单使用 增删改查。让NDatabase带你脱离ADO.net,各种SQL 语句,各种DBMS,各种CRM,IOC之类的烦恼。我们也不需要仓库设计模式了,你妹的。不要表了,不要设计数据库字段了。就这样!
- 策略模式与简单工厂模式的结合使用
- 简单工厂模式和策略模式结合使用php
- 使用反射来实现简单工厂模式
- 使用简单工厂模式出现程序集不能加载的问题的解决方案