Java 类的大量布尔标志输入
我有一个对话框,根据应用程序的状态、当前用户的安全性等显示各种内容。 我目前正在传入几个布尔标志,然后根据这些标志启用和/或隐藏UI组件。例如:Java 类的大量布尔标志输入,java,refactoring,Java,Refactoring,我有一个对话框,根据应用程序的状态、当前用户的安全性等显示各种内容。 我目前正在传入几个布尔标志,然后根据这些标志启用和/或隐藏UI组件。例如: new MyDialog(showOptionsTable, allowFooInput, allowBarInput, isSuperUser) 起初,这是一对旗帜,这很好。但是现在随着需求的变化,它已经演变成五个布尔标志的输入 处理这种行为的最佳做法是什么?这是我应该根据对话框的外观来分类的吗? 一旦你获得了超过两个或三个标志,我会考虑创建一个
new MyDialog(showOptionsTable, allowFooInput, allowBarInput, isSuperUser)
起初,这是一对旗帜,这很好。但是现在随着需求的变化,它已经演变成五个布尔标志的输入
处理这种行为的最佳做法是什么?这是我应该根据对话框的外观来分类的吗? 一旦你获得了超过两个或三个标志,我会考虑创建一个类来存储这些设置以保持你的设计干净。< P>使用动态添加行为到你的对话框 < P>设置My对话框(false,false,…)是预期的默认行为。(即:最常见的情况应该是all false。您可能需要反转标志的语义。) 现在,定义常量:
OPTION1 = 1
OPTION2 = 2
OPTION3 = 4
OPTION4 = 8
...
更改该方法以获取int options参数
public void MyDialog(int options) ...
现在叫它:
MyDialog(OPTION1 | OPTION3) // enable Opt1, opt2)
方法内部:
if (options & OPTION1) // use Option 1 config.
等等。如果GUI取决于应用程序的状态(一种状态导致另一种状态),您可以查看模式。其中,每个新状态将由不同的对象处理,您可以对标志是否应为go进行编码 即 并使用此状态显示对话框
new MyDialog(showOptionsTable, new InitialState() );
当应用程序的状态更改时,您将更改状态对象
public void actionPerfomed( ActionEvent e ) {
this.state = state.next();
repaint();
}
要绘制对话框的各个部分,请查询状态:
if( state.getFlags()[SECURITY] ) {
/// show security stuff
} if ( state.getFlags()[VIEW_ONLY] ) {
// enable/disable stuff
} ....
您可以更进一步,让状态定义呈现的内容
abstract class State {
public abstract JComponent getComponent();
public abstract State next();
}
因此,每个州都显示了不同的部分:
Dialog.this.setContentPane( state.getComponent() );
创建一个类以保存配置选项:
public class LayoutConfig
{
public boolean showOptionsTable = true;
public boolean allowFooInput = true;
public boolean allowBarInput = true;
public boolean isSuperUser = true;
}
...
LayoutConfig config = new LayoutConfig();
config.showOptionsTable = false;
new MyDialog(config);
这种方法可以轻松添加新选项,而无需更改界面。它还允许您添加非布尔选项,如日期、数字、颜色、枚举…要在Ben Noland answer的基础上构建,您可以将一些选项定义为枚举,然后使用varargs构造函数:
class MyDialog {
enum DialogOptions {
SHOW_OPTIONS_TABLE, ALLOW_FOO_INPUT, ALLOW_BAR_INPUT, IS_SUPER_USER
}
public MyDialog(DialogOptions ...options) { ... }
}
...
new MyDialog(DialogOptions.ALLOW_FOO_INPUT, DialogOptions.IS_SUPER_USER);
与许多事情一样,“这取决于”
我发现,如果我使用
enum
s作为布尔选择,这类内容的可读性会更高
public enum ShowOptionsTable { YES, NO }
public enum AllowFooInput { YES, NO }
public enum AllowBarInput { YES, NO }
public enum IsSuperUser { YES, NO }
new MyDialog(ShowOptionsTable.YES, AllowFooInput.NO, AllowBarInput.YES,
IsSuperUser.NO);
有了这样的枚举,使用带有大量布尔参数的代码变得容易理解。此外,由于您使用对象而不是布尔值作为参数,因此如果需要,您可以使用其他模式在以后轻松重构,如使用装饰器、外观或其他模式。如果参数都是布尔值,我更喜欢标记的枚举而不是设置类。如果你不能保证将来的安全,那就比后悔好。下面是标志的另一个实现:
[Flags]
public enum LayoutParams
{
OptionsTable = 1,
FooInput = 2,
BarInput = 4,
SuperUser = 8,
}
public MyDialog(LayoutParams layoutParams)
{
if (layoutParams & LayoutParams.OptionsTable)
{ /* ... Do Stuff ... */ }
}
public static MyDialog CreateBasic()
{
return new MyDialog(LayoutParams.OptionsTable | LayoutParams.BarInput);
}
根据您的显示将有多大不同,您可以考虑对显示类进行分类(即<代码> MyDialogSuperUser <代码>或SoMeSuCh)。你需要考虑到对话类输入的正交性以及如何表达正交性。
< P>我有一个最喜欢的方式来处理这个问题,但是它对于所有用例都是无效的。如果布尔值不是完全独立的(比如说存在一些无效的布尔值组合,或者布尔值组合是通过可识别的场景实现的。)我为状态创建一个枚举,然后定义一个保存标志的构造函数:public enum status {
PENDING(false,false),
DRAFT(true,false),
POSTED(false,true),
;
public boolean isSent;
public boolean isReceived;
status(boolean isSent, boolean isReceived) {
this.isSent = isSent;
this.isReceived = isReceived;
}
}
这样一段代码的优点是,可以相对简洁地构造枚举常量,但仍然允许代码只关注状态的一个特定方面。例如:
//I want to know specifically what the state is
if (article.state == status.PENDING)
// Do something
//I really only care about whether or not it's been sent
if (article.state.isSent)
// Do something
//I want to do something specific for all possible states
switch(article.state)
// A string of case statements
另一个优点是,如果您定义好了枚举,则永远不会达到非法状态:
if (article.state.isReceived && !article.state.isSent) {
// This block can never execute ever.
}
当然,并不是所有的时候布尔人之间都有逻辑关系,但我确实建议把它们映射出来。如果布尔数的子集具有逻辑关系,那么将其分解为枚举可能是值得的。也就是说,重构和子类化可能是一个更好的选择。我更喜欢枚举而不是原始整数。是的,但保持简单愚蠢——这只是修饰。修饰,这可能是C语言中的标准方式,但在Java中肯定是一种代码味道。至少我会在代码审查中批评它。我不想让我的API设计人员要求我们的API用户只需选择几个选项就可以进行位操作。您可以发布装饰器模式的伪示例吗?包含使用Window和WindowDecoratorTanks作为链接的经典示例。我不知道装饰图案的概念,但我不知道如何在这里应用它-/您可以为每个布尔值编写一个Decorator:即OptionTableDecorator、SuperUserDecorator等。这种设计允许您动态地向原始对话框添加新行为,您的布尔值被转换为一个Decorator链,维护起来更简单。希望有帮助:)你是说一个具有属性的JavaBean吗?当添加更多的复选框时,这将导致创建的状态数量呈指数级增长。如果这部分代码不太可能在t中增加,状态模式可能会更好
if (article.state.isReceived && !article.state.isSent) {
// This block can never execute ever.
}