具有一系列"instanceof"操作被认为是"代码味道".标准答案是"使用多态".在这种情况下我该怎么做?
基类有许多子类; 没有一个在我的控制之下.类似的情况是Java类Integer,Double,BigDecimal等.
if (obj instanceof Integer) {NumberStuff.handle((Integer)obj);}
else if (obj instanceof BigDecimal) {BigDecimalStuff.handle((BigDecimal)obj);}
else if (obj instanceof Double) {DoubleStuff.handle((Double)obj);}
Run Code Online (Sandbox Code Playgroud)
我确实可以控制NumberStuff等等.
我不想在几行代码中使用多行代码.(有时我将一个HashMap映射到一个IntegerStuff的实例,将BigDecimal.class映射到一个BigDecimalStuff的实例等等.但是今天我想要一些更简单的东西.)
我想要像这样简单的东西:
public static handle(Integer num) { ... }
public static handle(BigDecimal num) { ... }
Run Code Online (Sandbox Code Playgroud)
但是Java不会那样工作.
我想在格式化时使用静态方法.我正在格式化的东西是复合的,其中Thing1可以包含一个数组Thing2s和Thing2可以包含一个Thing1s数组.当我实现这样的格式化程序时,我遇到了问题:
class Thing1Formatter {
private static Thing2Formatter thing2Formatter = new Thing2Formatter();
public format(Thing thing) {
thing2Formatter.format(thing.innerThing2);
}
}
class Thing2Formatter {
private static Thing1Formatter thing1Formatter = new Thing1Formatter();
public format(Thing2 thing) {
thing1Formatter.format(thing.innerThing1);
}
}
Run Code Online (Sandbox Code Playgroud)
是的,我知道HashMap和更多代码也可以修复它.但相比之下,"instanceof"似乎更具可读性和可维护性.有什么简单但不臭吗?
注释已添加5/10/2010:
事实证明,将来可能会添加新的子类,而我现有的代码必须优雅地处理它们.在这种情况下,类上的HashMap不起作用,因为找不到类.一系列if语句,从最具体的开始到以最一般的结尾,可能是最好的:
if (obj instanceof SubClass1) …
Run Code Online (Sandbox Code Playgroud) java reflection polymorphism instanceof chain-of-responsibility
我有一个解析一些模板文件的代码,当它找到一个占位符时,它会用一个值替换它.就像是:
<html>
<head>
<title>%title%</title>
</head>
<body bgcolor="%color%">
...etc.
Run Code Online (Sandbox Code Playgroud)
在代码中,解析器找到这些,调用此函数:
string getContent(const string& name)
{
if (name == "title")
return page->getTitle();
else if (name == "color")
return getBodyColor();
...etc.
}
Run Code Online (Sandbox Code Playgroud)
然后用返回值替换原始占位符.
在实际情况中,它不是虚拟网页,并且可以发生许多(50+)个不同的占位符.
我的代码是C++,但我猜这个问题存在于任何语言中.我猜它更多的是关于算法和OO设计.唯一重要的是必须编译,即使我希望我没有任何动态/评估代码.
我虽然关于实施责任链模式,但它似乎并没有改善这种情况.
更新:我也关注另一个帖子中的这个评论.我应该关心它吗?
最近,我正在与另一个程序员讨论重构一个充满"if"语句的巨大(1000行)方法的最佳方法.
代码是用Java编写的,但我想这个问题也可能发生在C#等其他语言中.
为了解决这个问题,他建议使用责任链模式.他建议有一个基础"处理程序"类.然后,"Handler1","Handler2"等将扩展"Handler".
然后,处理程序将具有"getSuccessor"方法,该方法将返回null(如果它是链的最后一个)或链的下一个Handler.
然后,"的handleRequest(请求)"功能,要么处理请求,或者将它传递给下一个链条,如果没有以前的解决方案的工作,它将返回空值只是或抛出异常.
要向链中添加新的Handler,编码器将转到链的最后一个元素并告诉它有一个新元素.要做某事,他只需要在链的第一个元素上调用handleRequest.
为了解决这个问题,我建议使用不同的方法.
我还有一个基础"Handler"类,带有"Handler1","Handler2",就像之前提到的方法一样.
但是,没有"getSuccessor"方法.相反,我有一个Collection类,其中包含一个处理程序列表(Vector,一个ArrayList,或者在这种情况下最好的).
handleRequest函数仍然存在,但它不会将调用传播给下一个处理程序.它只会处理请求或返回null.
要处理请求,可以使用
for(Handler handle : handlers){
result = handle.handleRequest(request);
if(result!=null) return result;
}
throw new CouldNotParseRequestException(); //just like in the other approach
Run Code Online (Sandbox Code Playgroud)
或者,为了防止代码重复,可以将"parseRequest(request)"方法添加到集合类中.要添加一个新的处理程序,可以转到集合构造函数(或static {}块,或者等价物)并简单地添加代码"addHandler(new Handler3());".
对于这种方法,我错过了什么样的责任链优势?哪种方法最好(假设是一个最好的方法)?为什么?每种设计方法可能导致哪些潜在的错误和问题?
对于那些需要上下文的人来说,这是原始代码的样子:
if(x instanceof Type1)
{
//doSomething1
} else if(x instanceof Type2)
{
//doSomething2
}
//etc.
Run Code Online (Sandbox Code Playgroud) 在我目前的项目中,我经常发现自己经常使用责任链模式(对我来说经常是3次),我想知道我是否对解决方案过于热心.具体来说,我一直在使用Apache Commons 链项目.因此,我对它如何将一些复杂的可互换的应用程序逻辑简化为更具凝聚力和组织性的整体印象深刻.然而,项目中的一些新人似乎很难"得到它".你有什么经历?你在实施中遇到了什么问题?
到目前为止,我注意到的唯一问题就是当你试图处理需要关闭的对象时.将这些对象存储在Context类中会在完成链的执行时产生痛苦.我能够使用Filters而不是Commands来解决这个问题,但它似乎有点不直观,因为你的close语句通常离实例化对象的位置很远.
无论如何,我很想听到一些开发人员的想法,他们对我有这种模式的经验.
提前致谢.
我提出这个问题是因为几天前我在这里提出的另一个问题.
我必须解决一个特定的问题,在得到两个回复后,我意识到两个模式可以帮助解决这个问题(以及任何其他类似问题).
我的问题是:
这些模式之间究竟有什么区别?
我正在实施一系列责任模式.
我有不同的策略可以组合在一个列表中,我有一个处理策略列表的处理器.每个策略都可以处理CustomInput,并可以选择是否也应该处理其余策略.
interface Policy {
public boolean process(CustomInput input);
}
interface Processor {
public void process(List<Policy> policies, CustomInput input)
}
Run Code Online (Sandbox Code Playgroud)
我打算在策略列表上实现Processor循环,并检查每个策略的布尔结果,以了解是否继续使用其余策略.
我的同事建议将下一个策略传递给每个策略,让他们调用(或不调用)下一个策略(例如FilterChain).
我的问题如下:
我在第二个解决方案中没有看到任何好处(将下一个策略传递给当前处理的策略),而不是循环遍历每个策略并检查它的结果?
我需要构建一个过程,该过程将根据~200个验证规则验证记录.记录可以是~10种类型中的一种.从验证规则到记录类型存在一些细分,但存在大量重叠,这使我无法对验证规则进行干净整理.
在我的设计过程中,我正在考虑所有验证规则的责任链模式.这是一个好主意还是有更好的设计模式?
考虑一下你有几个验证.只有在要检查的对象属于某种类型时,这些验证才会生效.为什么我会在switch语句中使用一系列责任?
责任链示例
public class Executor {
@Inject
private ValidatorFactory validatorFactory;
public void execute(Konfiguration konfig) {
List<Statement> statements = konfig.getStatements();
AbstractValidator validator = validatorFactory.create();
for (Statement statement : statements) {
if (validator.validate(statement.getType())) {
crudService.execute(statement.getSql());
}
}
}
Run Code Online (Sandbox Code Playgroud)
validatorFactory创建Validators链.一个验证器看起来像
public class AddPrimaryKeyValidator extends AbstractValidator {
@Override
public boolean validate(Statement statement) {
if (SqlType.ADD_PK.getTyp().equals(statement.getType())) {
return doesTableAndPrimaryKeyExist(statement.getTabName());
}
return successor.validate(statement);
}
Run Code Online (Sandbox Code Playgroud)
switch语句的示例
public void execute(Konfiguration konfig) {
List<Statement> statements = konfig.getStatements();
for (Statement statement : statements) {
switch (statement.getType()) {
case "ADD_PK":
if …
Run Code Online (Sandbox Code Playgroud) java design-patterns switch-statement chain-of-responsibility
java ×5
decorator ×2
oop ×2
c++ ×1
instanceof ×1
list ×1
polymorphism ×1
reflection ×1
templates ×1