【问题标题】:How to accommodate new logics that needs to be part of the ap如何适应需要成为应用程序一部分的新逻辑
【发布时间】:2013-07-25 05:16:16
【问题描述】:

我的情况是 我有 API 。 执行 tday 的函数 CompleteFlow() 具有一些业务逻辑,例如 Step1() ,Step2()。

明天除了函数 A 之外,可能还需要调用另一个逻辑,例如 Step3()。

然后是 Step4() ..等等..

一般来说。

Class A
{

CompleteFlow()

}


CompleteFlow()
{
Step 1(),
Step 2().
....
....
....
}

就像我的顺序一样,将来可以添加新的业务逻辑。我需要针对这些类编写一个 UI 客户端。

最适合我的设计模式是什么。 (请举例)

【问题讨论】:

  • 您能说说您的步骤是什么样的吗?
  • 与上一步无关..每个都是孤立的步骤,它不会知道上一步是什么。

标签: algorithm oop design-patterns


【解决方案1】:

我建议将每一步都抽象出来,并确保它实现了由通用接口指定的契约。并收集容器中的所有步骤对象,您的 CompleteFlow 应该必须按顺序调用容器中的每个步骤对象。当你想添加一个新的步骤时,只需实现一个新类并将一个相同的对象添加到步骤容器中。

或者您可以让您的步骤类在工作流程步骤容器中注册。因此该容器完全独立于步骤。好的设计坚持松耦合。因此,您可以根据需要修改类。

根据您的评论,我看到调用步骤的顺序基本上是连续的。否则,您可能必须实现状态机或工作流引擎。

并提供具体的用例,可能有助于我们为您的查询提供更具体的答案。

  class IStep {
      public:
         virtual void execute() = 0;
  };

  class ConcreteStep1 : public IStep {
       public:
          void execute() {
             cout << "Doing Step1";
          }
  }

  vector<IStep> workflowSteps;
  workflowSteps.push_back(new ConcreteStep1());
  // Add other steps like this.

  void CompleteFlow() {
      for (vector<IStep>::iterator it = workflowSteps.begin() ; it != workflowSteps.end(); ++it)
         (*it)->execute();
  }

【讨论】:

  • 它是顺序的。可以请你放一些虚拟的类和接口,以便我可以完全可视化它。
【解决方案2】:

您可以尝试诸如责任链之类的方法,因此 UI 客户端调用将是这样的:

UI Client -----> Call Step1() // Suppose if you want to restrict the call to Step1(),
                              // pass some parameters in UI Client which you can handle
                     |        // in function calls
                     |        
                     V        
                 Call Step2()  // Otherwise pass the call to the next
                     |         //handler Step2().   
                     |
                     V
                  ......

通过这种方式,您可以从 UI 客户端控制您的函数调用,即它是应该在特定步骤中停止还是继续执行下一步函数。希望这可以帮助。 您也可以参考链接:http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern,其中解释了责任链。

【讨论】:

  • 好的。但问题是今天我知道 step1() 请求参数 A。所以我将传递参数 A。但是如果我的 step2() 需要参数 B,那么我将如何将参数从 UI 传递给这个?
  • 假设您将 3 作为 UI 函数的一个参数的值传递,并将条件检查放置在每个函数(Step1、Step2、Step3)中以获取参数值。在 Step3 中检查 value ==3 然后停止将其链接到下一个处理程序并停止执行。在这个过程中,会执行Step1、Step2、Step3。出于这个原因,我只是给出一个模糊的例子,您可以选择表示不同的参数值。
【解决方案3】:

您可以将所有步骤抽象为一个步骤链。步骤链将是一个可重用的类,因此它不特定于一个类。在你的案例类A

为有序的步骤创建一个接口,让步骤链按顺序执行。

public interface Step {
    public void execute();
}

public interface Ordered {
    public int getOrder();
    public void setOrder(int order);
}

public interface OrderedStep extends Step, Ordered {
}

比较器帮助对实现有序的实例进行排序。

public class OrderedComparator implements Comparator<Ordered> {
    public int compare(Ordered a, Ordered b) {
        if (a.getOrder() > b.getOrder()) {
            return 1;
        }

        if (a.getOrder() < b.getOrder()) {
            return -1;
        }
        return 0;
    }
}

步骤链将负责按指定顺序执行所有步骤。

public class OrderedStepChain {
    List<OrderedStep> steps = new ArrayList<OrderedStep>();

    public void addStep(OrderedStep step) {
        steps.add(step);
    }

    public void execute() {
        Collections.sort(steps, new OrderedComparator());

        for (OrderedStep step : steps) {
            step.execute();
        }
    }
}

一个简单的步骤实现。

public class OrderedStepImpl implements OrderedStep {
    public int order;

    public void setOrder(int order) {
        this.order = order;
    }

    public int getOrder() {
        return order;
    }

    public void execute() {
        System.out.println("Step#" + order + " executed");
    }
}

所有步骤都由步骤链处理,使用起来相当容易。将此功能添加到可能需要它的其他类中也更容易。

public class A {
    OrderedStepChain stepChain = new OrderedStepChain();

    // add steps backwards
    public void createSteps() {
        for (int i = 9; i > 0; i--) {
            OrderedStep step = new OrderedStepImpl();
            step.setOrder(i);
            stepChain.addStep(step);
        }
    }

    /* 
     * Other objects may interact with the step chain
     * adding additional steps.
     */
    public OrderedStepChain getStepChain() {
        return this.stepChain;
    }

    public void completeFlow() {
        stepChain.execute();
    }
}

当我运行单元测试时,输出是。

Step#1 executed
Step#2 executed
Step#3 executed
Step#4 executed
Step#5 executed
Step#6 executed
Step#7 executed
Step#8 executed
Step#9 executed

【讨论】:

  • 将步骤顺序与步骤绑定会降低步骤的可重用性
  • @KhaledAKhunaifer 感谢您的指点。相应地调整了我的答案。
【解决方案4】:

这是我的 Java 伪代码:

public class Input
{
    public Map<Object,Class> data;
    public Input ()
    {
        data = new TreeMap<Object,Class>();
    }
}

public interface Step
{
    public void execute (Input in);
    public void revert ();
}

// Map<StepID, <Step, StepPriority>>
public class StepChain
{
    Map<Long, Pair<Step,Long>> chain;

    public StepChain ()
    {
        chain = new TreeMap<Long, Pair<Step,Long>>();
    }

    public void addStep (Long stepId, Step step, Long stepPriority)
    {
        chain.put(stepId, new Pair<Step,Long>(step,stepPriority));
    }

    public Queue<Step> getStack ()
    {
        Stack<Step> stack= new Stack<Step>();
        Map<Step,Long> map = new TreeMap<Step,Long>();

        for (Pair<Step,Long> p : chain.getValues())
        {
            map.put(p.getFirst(), p.getSecond());
        }

        for (Step step : map.getKeySet())
        {
            stack.push(step);
        }

        return stack;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-21
    • 2022-11-13
    • 1970-01-01
    • 2018-03-16
    • 1970-01-01
    • 2017-05-30
    • 2015-11-10
    • 1970-01-01
    相关资源
    最近更新 更多