具有少量布尔参数的重构方法
Refactoring method with few boolean parameters
有一个很好的重构方法。例如,我们有这个带有标志的方法:
public void process(boolean hasLicense){
if (hasLicense){
System.out.println("has");
}else {
System.out.println("has not");
}
}
我们可以拆分成两种方法:
public void processWithLicense() {
System.out.println("has");
}
public void processWithoutLicense() {
System.out.println("has not");
}
但是这种方法呢?
public void process(boolean hasLicense, boolean isAdmin) {
if (hasLicense && isAdmin) {
System.out.println("success");
}
System.out.println("some code");
if (isAdmin){
System.out.println("add grants");
}
System.out.println("10 lines code");
if (isAdmin && !hasLicense){
System.out.println("something");
}
}
如何重构此方法并删除布尔参数?
How can I refactor this method and remove boolean parameters?
关于重构的事情是,这个决定在很大程度上取决于你想做什么,以及实际代码是什么样的:我可以提出建议,但这些可能或者可能不合适。
你可以在这里使用的东西是 Template Pattern:你可以定义一个类似这样的接口:
interface Template {
void part1();
void part2();
void part3();
}
然后将您的方法重构为:
public void process(Template template) {
template.part1();
System.out.println("some code");
template.part2();
System.out.println("10 lines code");
template.part3();
}
然后为 (admin/non-admin) x (license/no 许可证传入该接口的实现。
显然,如果您需要表示所有可能性,这会变得很大,因此您可能不想这样做。
如果反对传递 布尔值,您可以使用其他类型。 Effective Java 建议传递双元素枚举而不是布尔值,原因有很多,包括:
- 更具描述性:调用站点是自我记录的,其中使用了文字值
- 将来添加更多选项更容易
- 因为相邻参数的类型不同,所以更不容易弄错顺序
enum AdminState { IS_ADMIN, NOT_ADMIN }
enum LicenceState { HAS_LICENCE, NO_LICENCE }
public void process(AdminState adminState, LicenceState licenceState) {
if (licenceState == HAS_LICENCE && adminState == IS_ADMIN) {
System.out.println("success");
}
// ...
}
或者,如果您希望避免传递许多参数,您可以创建一个class 来保存许多参数:
class ProcessArgs {
boolean isAdmin() { ... }
boolean hasLicense() { ... }
}
然后传入:
public void process(ProcessArgs args) {
if (args.hasLicense() && args.isAdmin()) {
System.out.println("success");
}
// ...
}
这提出了如何初始化 ProcessArgs
的实例的问题:如果您只是有一个采用 2 个布尔值的构造函数,它对实现“不传递布尔值”,因为您刚刚将 2 个布尔值从方法移动到构造函数。
但是,它确实具有允许您在多个位置传递同一组参数的优势,而无需担心转置参数之类的事情。
有一个很好的重构方法。例如,我们有这个带有标志的方法:
public void process(boolean hasLicense){
if (hasLicense){
System.out.println("has");
}else {
System.out.println("has not");
}
}
我们可以拆分成两种方法:
public void processWithLicense() {
System.out.println("has");
}
public void processWithoutLicense() {
System.out.println("has not");
}
但是这种方法呢?
public void process(boolean hasLicense, boolean isAdmin) {
if (hasLicense && isAdmin) {
System.out.println("success");
}
System.out.println("some code");
if (isAdmin){
System.out.println("add grants");
}
System.out.println("10 lines code");
if (isAdmin && !hasLicense){
System.out.println("something");
}
}
如何重构此方法并删除布尔参数?
How can I refactor this method and remove boolean parameters?
关于重构的事情是,这个决定在很大程度上取决于你想做什么,以及实际代码是什么样的:我可以提出建议,但这些可能或者可能不合适。
你可以在这里使用的东西是 Template Pattern:你可以定义一个类似这样的接口:
interface Template {
void part1();
void part2();
void part3();
}
然后将您的方法重构为:
public void process(Template template) {
template.part1();
System.out.println("some code");
template.part2();
System.out.println("10 lines code");
template.part3();
}
然后为 (admin/non-admin) x (license/no 许可证传入该接口的实现。
显然,如果您需要表示所有可能性,这会变得很大,因此您可能不想这样做。
如果反对传递 布尔值,您可以使用其他类型。 Effective Java 建议传递双元素枚举而不是布尔值,原因有很多,包括:
- 更具描述性:调用站点是自我记录的,其中使用了文字值
- 将来添加更多选项更容易
- 因为相邻参数的类型不同,所以更不容易弄错顺序
enum AdminState { IS_ADMIN, NOT_ADMIN }
enum LicenceState { HAS_LICENCE, NO_LICENCE }
public void process(AdminState adminState, LicenceState licenceState) {
if (licenceState == HAS_LICENCE && adminState == IS_ADMIN) {
System.out.println("success");
}
// ...
}
或者,如果您希望避免传递许多参数,您可以创建一个class 来保存许多参数:
class ProcessArgs {
boolean isAdmin() { ... }
boolean hasLicense() { ... }
}
然后传入:
public void process(ProcessArgs args) {
if (args.hasLicense() && args.isAdmin()) {
System.out.println("success");
}
// ...
}
这提出了如何初始化 ProcessArgs
的实例的问题:如果您只是有一个采用 2 个布尔值的构造函数,它对实现“不传递布尔值”,因为您刚刚将 2 个布尔值从方法移动到构造函数。
但是,它确实具有允许您在多个位置传递同一组参数的优势,而无需担心转置参数之类的事情。