重构改善既有代码设计--以工厂函数取代构造函数
以工厂函数取代构造函数
Employee (int type) { _type = type; } =======================> static Employee create (int type) { return new Employee(type); }
动机
你可能常常需要根据type code 创建相应的对象, 现在, 创建名单中还得加上subclasses, 那些subclasses 也是根据type code 来创建。你也可以令你的factory method 根据参数的个数和型别, 选择不同的创建行为。
做法
-
新建一个factory method , 让它调用现有的构造函数 将「 对构造函数的调用」 替换为「 对factory method 的调用」 每次替换后, 编译并测试 将构造函数声明为private 编译
范例
class Employee { private int _type; static final int ENGINEER = 0; static final int SALESMAN = 1; static final int MANAGER = 2; Employee (int type) { _type = type; } } ==========================> // 有一个switch 语句。 如果添加一个新的subclass, 就必须记得更新这里的switch 语句, 而我又偏偏很健忘。 static Employee create(int type) { switch (type) { case ENGINEER: return new Engineer(); case SALESMAN: return new Salesman(); case MANAGER: return new Manager(); default: throw new IllegalArgumentExcption("Incorrect type code value"); } } ==========================> // 绕过这个switch语句最好的办法是使用Class.frName()。 static Employee create (String name) { try { return (Employee) Class.forName(name).newInstance(); } catch (Exception e) { throw new IllegalArgumentException ("Unable to instantiate" + name); } } // 让create (int type) 调用create(String name) class Employee { static Employee create (int type) { swtich (type) { case ENGINEER: return create("Enginerr"); case SALESMAN: return create("Salesman"); case MANAGER: return create("Manager"); default: throw new IllegalArgumentException("Incorrect type code value"); } } } ================================> // 移除int版本 // 另一个「必须谨慎使用(Class.forName() 」 的原因是: 它向用户暴露了subclass 名称。 Employee.create("Engineer");
范例2: 以明确函数创建subclass 如果你只有少数几个subclasses, 而且它们都不再变化, 这条途径是很有用的。
class Person... static Person createMale(){ return new Male(); } static Person createFemale(){ return new Female(); } // 然后可以把这个调用 Person kent = new Male(); // 替换为 Person kent = Person.createMale();