【问题标题】:Enum vs Lookup table vs Enum reflection vs State pattern枚举 vs 查找表 vs 枚举反射 vs 状态模式
【发布时间】:2020-03-23 08:10:04
【问题描述】:

我将要构建的软件将涉及很多不同状态之间的“应用程序”切换。可以完成的某些任务取决于应用程序所处的状态。我正在考虑使用枚举作为状态

public class Application
{
  public int Id {get;set;}
  public Status {get;set;}
}
public enum Status
{
  [Description("New")]New = 1, [Description("Closed")]Closed = 2
}

但后来我想在数据库中使用查找表可能会很好,因为状态确实会经常更新/重新排序

table status (id int pk, desc string, sort_order int)
table application (id int pk, status_id int fk)

在我的情况下,我需要做类似的事情

if (application.Status == Status.New)
{ //do something }
else if (application.Status == Status.Closed)
{ //do other things }

我认为使用枚举更容易实现上述情况。但是,当涉及到更新状态排序顺序或描述时,会非常困难。

我应该使用反射根据查找表中的值动态创建枚举吗?或者我应该使用状态模式?我看到枚举相关的问题是性能影响。而状态模式会产生大量的冗余代码。

你怎么看?提前致谢!

【问题讨论】:

    标签: design-patterns reflection enums state-pattern


    【解决方案1】:

    你不应该在你的代码中到处使用这个检查

    if (application.Status == Status.New)
    { //do something }
    else if (application.Status == Status.Closed)
    { //do other things }
    

    改为使用状态模式。每当应用程序的模式发生变化时更改状态并将所有调用转发到状态的方法。您将拥有更简洁、更易于维护的代码。

    至于改变状态,与状态模式无关。因此,您可以使用任何优雅的方法。

    【讨论】:

      【解决方案2】:

      我会创建一个包含差异的 Status 类,然后调用它们。所以(在 ​​Python 中):

      class StatusZero(object):
          def call_me(self, app):
             print 'Hello, from ' + app.name
             return db.prepare_specific_status_zero_request()
      
      
      class StatusOne(object):
          def call_me(self, app):
              print 'Hi, from ' + app.name
              return db.prepare_specific_status_one_request()
      
      states = { 'status_zero' : StatusZero(), 'status_one' : StatusOne() }
      
      class Application(object):
          name = 'My App'
          status = states['status_zero']
      
          def change_state(self, state):
              status = state
      
          def call_me(self):
              state_key = self.status.call_me(self)
              self.change_state(states[state_key])
      

      快速、易于保持功能分区,并且在状态之间具有合理的继承模式,您可以共享没有区别的功能。

      【讨论】:

      • 你如何处理从数据库中检索并转换为对象位而不使用我在答案 3 中提到的 if else 语句?
      • 我想我很难理解这个问题。每个 Status 对象都可以包含您想要的任何代码——如果有必要,包括硬连线强制转换。 Application 对象可以保持不变;它调度与内部状态不同的调用。
      • 我的问题是如何在将数据表转换回正确状态的对象时避免手写 if else 语句,在您的示例中,如何在没有 if else 语句的情况下将数据行转换回 StatusZero 或 StatusOne ?
      • 哦,你的意思是通过数据库调用的结果来驱动应用程序的状态?理想情况下,“下一个状态”将作为 int 存储在数据库中,您可以使用它来查找状态数组中的索引。但是字符串在哈希查找中也同样有效。我将编辑示例。
      【解决方案3】:

      我的理解是状态模式非常适合仅 UI 或仅在内存中执行,在我的情况下,当从应用程序表中检索数据时,仍然需要 if else 语句来确定要转换到的对象。

      public AbstractApplication convert_db_application_to_object(obj db_application)
      {
         AbstractApplication app;
         if (db_application.Status == (int)Status.New)
            app = application_factory.create(application_state_new);
         else if(db_application.Status == (int)Status.Closed)
            app = application_factory.create(application_state_closed);
      
         return app;
      }
      

      我不认为这是一个优雅的解决方案 因为我仍然需要一个枚举或查找表来将应用程序状态保存到数据库中

      【讨论】:

        猜你喜欢
        • 2011-09-02
        • 1970-01-01
        • 2023-03-16
        • 2013-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-01
        相关资源
        最近更新 更多