假设商业模式中有两个属性,例如国家和类型,我们需要为每个国家和每种类型处理不同的逻辑。
if(country=="us"){
if(type=="type1){
usType1Handler.Execute();
}
else if(type=="type2"){
usType2Handler.Execute();
}
.
.
.
else{
usDefaultHandler.Execute();
}
}
else if(country=="uk"){
if(type=="type1){
ukType1Handler.Execute();
}
else if(type=="type2"){
ukType2Handler.Execute();
}
.
.
.
else{
ukDefaultHandler.Execute();
}
}
else{
throw exception("unknown country");
}
将有很多if混合和匹配特定于每个国家/地区类型组合的每个实现。我们可以使用任何设计模式来处理这种情况吗?
答案 0 :(得分:0)
我建议在这个例子中使用嵌套开关:
switch (country)
{
case "us":
switch (type)
{
case "type1":
usType1Handler.Execute();
break;
case "type2":
usType2Handler.Execute();
break;
default:
break;
}
break;
case "uk":
switch (type)
{
case "type1":
ukType1Handler.Execute();
break;
case "type2":
ukType2Handler.Execute();
break;
default:
break;
}
break;
}
答案 1 :(得分:0)
您可以使用两种模式的组合来改善这种情况Chain of Responsibility
&& Strategy Pattern
。
Strategy Pattern
- 这种模式将帮助您解决国家的条件问题。您必须为我们系统中的每个国家/地区制作AbstractCountryStrategy
+具体Strategy
课程。 Strategy
类将包含一个非常简单的代码行(使用其他模式的行Chain of Responsibility
)
class USCountryStrategy {
public void execute(type) {
new USCountryTypeAHandler()
.setNext(new USCountryTypeBHandler()
.setNext(...))
.executeBasedOn(type)
}
}
Chain of Responsibility
- 这个模式将帮助你解决类型的条件(但是你仍然需要使用一个小的if / else来判断你的当前处理程序是否附加了下一个处理程序) 总体构思:对于每种类型,您都会有一个小班,检查它是否能够解决您的请求......类似于:
if(paramType.equals(this.type)
this.execute();
// if I can solve your request than I'll execute it myself
else if(this.next)
this.next.executeBasedOn(paramType);
// if I can't solve your request than I'll pass it on to the next handler
else
throw RuntimeException(...)
// nobody can solve your request (because I can't && this.next is null)
是的,当您切换代码时它很有用,请记住,您很快就必须更改此功能/类。交换机不可扩展,难以维护,速度非常快(“意大利面条代码”),您可能需要在代码库中使用它两次。
有关更好和更好的信息,请参阅https://github.com/kamranahmedse/design-patterns-for-humans完整的例子。
答案 2 :(得分:0)
您的用例非常适合策略+工厂模式实施。您应该有工厂来移出处理程序的实例化部分。正如您所看到的,我们还没有废除if-else块,而只是将它们移动到更易于管理的类中。毫无疑问,它增加了类的数量,但是这有助于您使代码可扩展,并且从长远来看可以减少错误。您可以根据需要添加任意数量的国家/地区,而无需触及现有代码。这可确保您不会在现有功能中引入错误。此外,如果你想要你可以让工厂返回CountryFactory,这将更好。这样,无论您将来有多少国家/地区和类型,您的“YourExecutingClass”始终保持不变。
{% extends 'layout.html.twig' %}
{% block content %}
{% for content in contents %}
// here you have access to a singular content object
{% endfor %}
{% block content %}
答案 3 :(得分:0)
这很简单。只需将所有处理程序添加到字典中,其中键是Country / Type组合,值是处理函数。
创建字典并添加所有处理程序:
Dictionary<string, Handler> processor = new Dictionary<string, Handler>()
{
{ "us,type1", usType1Handler },
{ "us,type2", usType2Handler },
{ "us", usDefaultType2Handler },
{ "uk,type1", ukType1Handler },
}
//...etc
然后,只需搜索字典并执行:
string key = String.Join(",", new[] { country, type })
bool success = processor.TryGetValue(key, out Handler handler);
if (success)
{
handler.Execute();
}
else
{
throw new Exception("unknown country");
}
答案 4 :(得分:0)
这里关键字是 execute(),它有no_countries X no_types变种数。要使用OO方法,您必须将这些组合分配到不同的类中。以大量具体课程为代价,您可以购买可扩展的解决方案。
使用策略:有人必须持有/创建这些策略并在需要时提供。如果策略不是国家/地区类型组合的唯一,那么您可以节省变化。当没有状态变化时,策略通常很有用。
责任链 - 此处的变体将由处理程序处理。处理程序必须决定它是否可以处理给定的情况(可能基于国家类型的组合),但如果变体可以处理多个组合,那么你将在处理程序中获得小的if。
两者都可以延期,但不可避免。