重构代码条件部分的更好方法
Better approach to refactor conditional part of the code
我正在尝试重构一段给定的代码,如下所述:
原始代码:
Method(URL link)
{
if(ConditionA(link))
{
MehodA(link);
}else if(ConditionB(link))
{
MehodB(link);
}else if(ConditionC(link))
{
MehodC(link);
}else if(ConditionD(link))
{
MehodD(link);
}
}
以上代码可能会随着将来可能出现的新情况而增加。重构后,我能够将代码分成多个 classes,每个都专注于单一职责,因此降低了初始复杂性,如下所示:
重构后:
METHOD(URL link)
{
ConditionalHandlerClass obj = new ConditionalHandlerClass(link);
ConditionalHandlerClass.HandleLinkProcessing();
}
Class ConditionalHandlerClass
{
URL link;
IConditionalProcess process;
public ConditionalHandlerClass(URL _link)
{
link = _link;
}
public void HandleLinkProcessing()
{
if(ConditionA(link))
{
process = new ProcessA(link);
}else if(ConditionB(link))
{
process = new ProcessB(link);
}else if(ConditionC(link))
{
process = new ProcessC(link);
}else if(ConditionD(link))
{
process = new ProcessD(link);
}
process.Handle();
}
}
interface IConditionalProcess
{
void handle();
}
class ProcessA() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
class ProcessB() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
class ProcessC() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
class ProcessD() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
但我看到 class ConditionalHandlerClass 中的 HandleLinkProcessing() 方法仍会随着不断添加新条件而继续增加。
您能否建议我如何使此实现更好,以便在添加新的 ConditionE() 和 MethodE() 调用流时不应该更改 class 之类的 ConditionalHandlerClass。因此,即使添加了新条件,也可以一次性降低复杂性 class。
我正在 objective c 中编写这段代码。
一种可能的方法是保留 Predicate<URL>
和 Consumer<URL>
对的集合。例如,这样的结构可能是 LinkedHashMap
,它保持插入顺序。
LinkedHashMap<Predicate<URL>, Consumer<URL>> ops = new LinkedHashMap<> {{
put(::ConditionA, ::MethodA);
put(::ConditionB, ::MethodB); ....
}}
void processURL(URL link) {
for(Map.Entry<...,...> entry : ops.entrySet()) {
if (entry.getKey().test(link)) {
entry.getValue().accept(link);
break;
}
}
}
编辑:标签 Java 在我写答案时消失了。我不是 Objective C 流利的,但是,与语言无关的原则。
可能会为处理程序引入策略并迭代它们。处理程序列表可以在运行时或某些静态上下文中初始化,但至少可以避免创建 mega-if-construct
编辑 抱歉我的 Java-伪代码...
interface LinkHandler() {
boolean accepts(URL link);
void handle(URL link);
}
public static void main( ...) {
List<LinkHandler> handlers = ...
URL urlToCheck = new URL( ... );
for( LinkHandler handler : handlers ) {
if( handler.accepts(urlToCheck) ) {
handler.handle(urlToCheck);
break;
}
}
}
我认为您的方向是正确的。诚然,处理可以通过无数种方式完成(并且通过 DI 进行构造函数注入,如果需要的话,你不需要处理大部分)但这是一种方法,它由 Handler class 的可重用实例与条件和执行逻辑...
public interface IConditional
{
bool Evaluate(Url link);
}
public class ConditionA : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public class ConditionB : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public class ConditionC : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public class ConditionD : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public interface IProcessor
{
void Process(Url link);
}
public class MethodA : IProcessor
{
public void Process(Url link)
{
// whatever A does?
}
}
public class MethodB : IProcessor
{
public void Process(Url link)
{
// whatever B does?
}
}
public class MethodC : IProcessor
{
public void Process(Url link)
{
// whatever C does?
}
}
public class MethodD : IProcessor
{
public void Process(Url link)
{
// whatever D does?
}
}
public class Handler
{
private IConditional conditional;
private IProcessor processor;
public Handler(
IConditional conditionalReference,
IProcessor processorReference)
{
this.conditional = conditionalReference;
this.processor = processorReference;
}
public bool Handle(Url link)
{
bool handled = false;
if (this.conditional.Evaluate(link)
{
this.processor.Process(link);
handled = true;
}
return handled;
}
}
public class Program
{
public static void Main()
{
Handler[] orderedHandlers = new []
{
new Handler(new ConditionA(), new MethodA()),
new Handler(new ConditionB(), new MethodB()),
new Handler(new ConditionC(), new MethodC()),
new Handler(new ConditionD(), new MethodD()),
};
Url link = new Url("xxx");
foreach(Handler handler in orderedHandlers)
{
if(handler.Handle(link))
{
break;
}
}
}
}
我正在尝试重构一段给定的代码,如下所述:
原始代码:
Method(URL link)
{
if(ConditionA(link))
{
MehodA(link);
}else if(ConditionB(link))
{
MehodB(link);
}else if(ConditionC(link))
{
MehodC(link);
}else if(ConditionD(link))
{
MehodD(link);
}
}
以上代码可能会随着将来可能出现的新情况而增加。重构后,我能够将代码分成多个 classes,每个都专注于单一职责,因此降低了初始复杂性,如下所示:
重构后:
METHOD(URL link)
{
ConditionalHandlerClass obj = new ConditionalHandlerClass(link);
ConditionalHandlerClass.HandleLinkProcessing();
}
Class ConditionalHandlerClass
{
URL link;
IConditionalProcess process;
public ConditionalHandlerClass(URL _link)
{
link = _link;
}
public void HandleLinkProcessing()
{
if(ConditionA(link))
{
process = new ProcessA(link);
}else if(ConditionB(link))
{
process = new ProcessB(link);
}else if(ConditionC(link))
{
process = new ProcessC(link);
}else if(ConditionD(link))
{
process = new ProcessD(link);
}
process.Handle();
}
}
interface IConditionalProcess
{
void handle();
}
class ProcessA() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
class ProcessB() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
class ProcessC() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
class ProcessD() : IConditionalProcess
{
void handle()
{
// Business Logic here
}
}
但我看到 class ConditionalHandlerClass 中的 HandleLinkProcessing() 方法仍会随着不断添加新条件而继续增加。
您能否建议我如何使此实现更好,以便在添加新的 ConditionE() 和 MethodE() 调用流时不应该更改 class 之类的 ConditionalHandlerClass。因此,即使添加了新条件,也可以一次性降低复杂性 class。
我正在 objective c 中编写这段代码。
一种可能的方法是保留 Predicate<URL>
和 Consumer<URL>
对的集合。例如,这样的结构可能是 LinkedHashMap
,它保持插入顺序。
LinkedHashMap<Predicate<URL>, Consumer<URL>> ops = new LinkedHashMap<> {{
put(::ConditionA, ::MethodA);
put(::ConditionB, ::MethodB); ....
}}
void processURL(URL link) {
for(Map.Entry<...,...> entry : ops.entrySet()) {
if (entry.getKey().test(link)) {
entry.getValue().accept(link);
break;
}
}
}
编辑:标签 Java 在我写答案时消失了。我不是 Objective C 流利的,但是,与语言无关的原则。
可能会为处理程序引入策略并迭代它们。处理程序列表可以在运行时或某些静态上下文中初始化,但至少可以避免创建 mega-if-construct
编辑 抱歉我的 Java-伪代码...
interface LinkHandler() {
boolean accepts(URL link);
void handle(URL link);
}
public static void main( ...) {
List<LinkHandler> handlers = ...
URL urlToCheck = new URL( ... );
for( LinkHandler handler : handlers ) {
if( handler.accepts(urlToCheck) ) {
handler.handle(urlToCheck);
break;
}
}
}
我认为您的方向是正确的。诚然,处理可以通过无数种方式完成(并且通过 DI 进行构造函数注入,如果需要的话,你不需要处理大部分)但这是一种方法,它由 Handler class 的可重用实例与条件和执行逻辑...
public interface IConditional
{
bool Evaluate(Url link);
}
public class ConditionA : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public class ConditionB : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public class ConditionC : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public class ConditionD : IConditional
{
public bool Evaluate(Url link)
{
return true; // your conditional logic here
}
}
public interface IProcessor
{
void Process(Url link);
}
public class MethodA : IProcessor
{
public void Process(Url link)
{
// whatever A does?
}
}
public class MethodB : IProcessor
{
public void Process(Url link)
{
// whatever B does?
}
}
public class MethodC : IProcessor
{
public void Process(Url link)
{
// whatever C does?
}
}
public class MethodD : IProcessor
{
public void Process(Url link)
{
// whatever D does?
}
}
public class Handler
{
private IConditional conditional;
private IProcessor processor;
public Handler(
IConditional conditionalReference,
IProcessor processorReference)
{
this.conditional = conditionalReference;
this.processor = processorReference;
}
public bool Handle(Url link)
{
bool handled = false;
if (this.conditional.Evaluate(link)
{
this.processor.Process(link);
handled = true;
}
return handled;
}
}
public class Program
{
public static void Main()
{
Handler[] orderedHandlers = new []
{
new Handler(new ConditionA(), new MethodA()),
new Handler(new ConditionB(), new MethodB()),
new Handler(new ConditionC(), new MethodC()),
new Handler(new ConditionD(), new MethodD()),
};
Url link = new Url("xxx");
foreach(Handler handler in orderedHandlers)
{
if(handler.Handle(link))
{
break;
}
}
}
}