【问题标题】:How to handle payment types with varying properties in the most elegant way如何以最优雅的方式处理具有不同属性的支付类型
【发布时间】:2010-04-23 00:11:52
【问题描述】:

我正在使用 ASP.NET MVC 2。

为了简单起见,我有三种付款方式:信用卡、电子支票或“稍后向我收费”。我想:

  1. 选择一种付款方式
  2. 在我的视图中显示一种付款类型的一些字段
  3. 使用这些字段(特定于类型)运行一些逻辑
  4. 显示确认视图
  5. 使用这些字段(特定于类型)运行更多逻辑
  6. 显示收据视图

每种付款类型都有特定于该类型的字段...可能有 2 个字段,也可能更多。目前,我知道有多少和哪些字段,但可以添加更多。我相信对我的观点来说最好的事情是对每种付款类型都有一个部分视图来处理不同的字段,并让控制器决定要呈现哪个部分(如果你有更好的选择,我愿意)。我真正的问题来自视图之间控制器中发生的逻辑。每种付款类型都有可变数量的字段。我想保持所有的强类型,但感觉某种字典是唯一的选择。添加到根据付款类型运行的特定逻辑。

为了保持强类型化,我为每种支付类型创建了一个类。没有接口或继承类型,因为每个付款类型的字段都不同。然后,我为每种付款类型提供了一个 Submit() 方法。然后,当控制器决定显示哪个局部视图时,它还分配提交操作的目标。

这不是优雅的解决方案,感觉非常错误。我伸出手来。你会怎么做呢?

【问题讨论】:

    标签: c# asp.net-mvc design-patterns


    【解决方案1】:

    例如,Order 对象并不真正关心特定的支付类型是一件好事——例如,只知道有一个 PledgedAmount 和一个 DepositedAmount 属性就足够了类来完成它的工作(例如,“如果没有通过任何付款方式收取订单,不要让自己进入已发货状态,我真的不在乎,只要它以某种方式收费,我很酷”)。

    UI 并不真正关心的另一件事是:您要么编写 switch 来加载正确的视图并完成它,要么最终创建一个类似于字典的字段、规则和验证元数据集合并让 UI 动态生成。

    例如,当我为我的一个应用程序添加国际地址支持时,我采用了后一种方法。我将地址抽象为一组通用字段:AdministrativeAreaMunicipality 等,并定义了一个AddressScheme 类,该类为每个字段定义了AddressFieldRules,说明是否需要它,如果应该使用正则表达式应用,如果有一组特定的允许值等。这是适当的,因为我们可以随时在允许列表中添加或删除国家/地区,而无需重新编译和重新部署应用程序; UI 可以根据AddressScheme 动态生成自身,而AddressScheme 本身是从数据库中加载的。甜蜜。

    但是您真的会 (a) 非常频繁地添加支付类型,还是 (b) 无需重新编译您的应用程序?有时您确实需要一个真正的烤面包机而不是带有面包和其他基于酵母的商品褐变模块的早餐烹饪机,所以只需添加一个开关或字典,将类型映射到正确的视图:我认为它完全可以接受UI 必须能够区分这些类型,更重要的是,您可以自定义编写和定制每种类型的表示 - 但更高层的部分可能会受益于一些抽象。 I talked about that in my answer to a different question related to billing.

    在您的示例中,您可以共享步骤 1、4 和 6 的通用代码,但将步骤 2、3 和 5 委托给特定的 UI 方法和视图。世界仍将旋转。

    我的两分钱。祝你好运!

    【讨论】:

    • 这就是我团队中的其他人所说的。我喜欢烤面包机的比喻。
    【解决方案2】:

    听起来您有三个不同的工作流程,每个工作流程都与用户选择的不同付款方式有关。虽然您只明确指出第 3 步和第 5 步有支付特定问题,但似乎第 1 步之后的所有内容都必须显示支付特定信息(除非在第 4 步中用户没有确认支付特定信息,并且在第 6 步中他们的收据没有'不表明他们是如何付款的)。

    在这种情况下,您可能会为自己制造更大的混乱,试图将所有这些组合到一个工作流程中,而不是为每种支付类型创建不同的控制器,将任何常见行为分解出来以供三种路径中的每一种重用.

    顺便说一句,虽然您表示您没有使用界面,但您给出的原因似乎有点令人不安。如果支付类型包含相同的字段,听起来您可能使用了一个接口。接口用于定义行为契约,因此您不应该使用它们来定义公共数据。

    【讨论】:

    • 常见的行为不能是 IPaymentMethod.MakePayment() 吗?
    • 如果 PaymentMethod 是您决定放置实际支付业务逻辑的地方,那么可以,但我认为 PaymentMethod 可能不适合这种逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多