这是一个设计模式吗?

4

我需要制作一些与财务有关的数据报告,在进行计算时,会遇到很多'if then'的情况:如果是大客户,则减去10%,如果邮政编码等于'10101',则加上10%,如果当天是星期六,则进行复杂的计算等。

因此,我曾经阅读过这种示例,他们所做的是(希望我记得清楚)创建一个包含一些基本信息的类,并使其能够添加各种计算对象。

所以,将我记住的内容放入伪代码中:

Basecalc bc = new baseCalc();
//put the info in the bc so other objects can do their if
bc.Add(new Largecustomercalc());
bc.Add(new PostalcodeCalc());
bc.add(new WeekdayCalc());

如果 BC 运行所有已添加的 Calc 对象的 Calc() 方法,那么它们必须能够看到 Basecalc 属性以正确执行计算逻辑。

因此,所有 if 的不同 Calc 对象中,而不是全部在 Basecalc 中。

这样说您是否明白了呢?

我在想这是否是某种设计模式?


5
你好,看起来你在寻找装饰器模式?(有点类似) - Brian Roach
这听起来与《Head First设计模式》中装饰器的描述非常相似(他们以计算热饮价格为例)。也许你在那里读过它? - Martin Smith
责任链模式或策略模式? - dtb
责任链模式看起来很像组合模式,不是吗? - Michel
@Brian Roach:我刚刚阅读的有关装饰器对象的示例都是关于添加到组件的装饰器(就像我想要的,将计算器添加到基础对象),但在这些示例中,所有装饰器都为自己做某些事情,它们不与组件进行交互。装饰器是否也允许更改组件对象的状态? - Michel
4个回答

5
正如dtb所建议的那样,"责任链模式"似乎最适用于这里,但稍有变化:通常情况下,责任链找到一个处理程序,然后退出。如果一个大客户在星期六订购了商品,你需要执行两个处理程序。请注意,这是一个非常棘手的扩展,因为你的对象可能已经在此期间发生了改变,而处理程序的顺序变得重要起来。这可能非常棘手。例如,如果有10美元的折扣和10%的折扣怎么办?现在操作的顺序很重要,除非两者都作用于原始价格。我想你明白我的意思。
重要的是要认识到设计模式并不是清晰明确的,因此通常没有一个正确的答案。尽管如此,我仍然认为这非常接近责任链模式,而且与其他被提到的模式相距较远。
首先,希望具体实现能够执行检查,以确定它们是否实际适用于手头的物品,这对于责任链来说是典型的。
其次,你需要的行为将根据对象中的实际数据而有所不同。"策略模式"只是封装了不同的算法,从本质上讲,它们都实现了相同的事情(例如,你可以有不同的策略来计算10%的折扣,但它们应该产生相同的值)。
"命令模式"是一种解耦模式,用于执行操作的实际请求,例如,如果你想让其他人计算折扣,你会为此生成一个命令对象。实际上,(多播)事件的处理程序通常是责任链。
"组合模式"适用于树状结构,你可以像在现实世界中一样组合对象。这与前面提到的问题有关:如果将责任链表示为退化的子树(没有分支),那么你将拥有一个有序列表,并且你可以表示先减去10美元,然后再打10%的折扣,或者反过来。从这个意义上讲,它可以被理解为高度退化的组合模式。组合模式可以用来描述具体的打折方案。尽管如此,选择和应用方案仍然是责任链的工作。
就像我说的,这些并不是清晰明确的术语,它们彼此之间密切相关,通常以变化(和滥用)形式出现,最重要的是,每个模式都需要一些针对特定问题的修改。尽管如此,我更喜欢坚持责任链的术语,稍加变化,因为我认为它最接近你描述的情况。

<bow>没错!在问题中也必须包含排序。非常感谢您详尽的回答!</bow> - Michel

3
似乎对于我来说,这就是策略模式。或许还与组合模式混合使用,因为您可以将计算实现添加到对象中。

我已经阅读了关于这种策略的内容:“更简单地说,一个对象及其行为被分离并放入两个不同的类中。这允许您随时切换正在使用的算法。” 这听起来正是我想做的事情,我也会检查一下组合模式。 - Michel
我也在考虑使用策略模式+组合模式。 - Damian Powell

1

那里似乎有两个模式在起作用,这取决于你所关注的内容。如果你正在谈论通过标准的“计算”方法将工作委派给项目列表,那么这是命令模式的一个例子。如果你正在谈论计算器类的实现,那就是装饰器模式


0

这不是责任链模式,责任链模式有完全不同的目的。它是命令模式(没有撤销/重做)和组合模式(组合命令)的结合体。正如其他人指出的那样,您也可以考虑将其作为策略的一部分,但再次,它对于成为策略的好例子来说过于退化了。有些人可能会称其为“内部DSL”。 正如大多数人所指出的:您无法真正定义它是什么,因为它取决于您的观点。如果您的计算方法不止一个,并且遍历算法将调用所有这些方法 - 或者根据操作数调用其中的一个子集 - 那么它将是策略,唯一确定的是“组合”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接