首页 > 解决方案 > C#正确使用策略模式的方法

问题描述

我正在尝试重构我的代码。目前,对于类似的功能,我有不同的方法名称,如下所示。

public interface IReminderService
{
    Task GenerateInviteReminders(string executedBy);
    Task GenerateBookingReminders(string executedBy);
}

但想使用类似下面的东西。但不确定如何在 switch case 中传递参数来设置策略。接口是使用 IOC 注入的。或者请让我知道重构代码的正确方法。

public interface IReminderStrategy
{
    Task GenerateReminders(string executedBy);
}

public class StrategyA : IReminderStrategy
{
    public StrategyA(IInterfaceA a, IInterface b)
    {}
}

public class StrategyB : IReminderStrategy
{
    public StrategyB(IInterfaceA a, IInterface b)
    {}
}   


public class ExampleService {
    private readonly IInterfaceA _a;
    private readonly IInterfaceB _b;
    public ExampleService(
        IInterfaceA a,
        IInterfaceB b
    ) {}
    switch case(string messageType)
    {
        IReminderStrategy strategy;
        case "A":
            strategy = new StrategyA(?????)
            break;
        case "B":
            strategy = new StrategyB(?????)
            break;          
    }
}

标签: c#design-patterns

解决方案


首先,我经常使用策略或模板方法模式,因为您利用了动态调度或多态性,并且您大多摆脱了 if-else 块。我的意思是你把这个逻辑放在一个地方,这样可以防止 if-else 分散到多个地方。为了进一步研究,您可以将它们与函数式编程中的高阶函数进行比较。

public interface IReminderStrategy
{
    Task GenerateReminders(string executedBy);
}

public class InviteReminder : IReminderStrategy
{
    private IInterfaceA _a;
    private IInterfaceB _b;
    public InviteReminder(IInterfaceA a, IInterface b){
       _a = a; _b = b;
    }

    public Task GenerateReminders(String executedBy) {
       _a.doSomething;
       _b.doSomething;
       //do invite reminder specific actions here.
    }

}

public class BookingReminder : IReminderStrategy
{
    private IInterfaceA _a;
    private IInterfaceB _b;
    public BookingReminder(IInterfaceA a, IInterface b){
       _a = a; _b = b;
    }

    public Task GenerateReminders(String executedBy) {
       _a.doSomething;
       _b.doSomething;
       //do booking reminder specific actions here.
    }
}   


public static class ReminderFactory {

    //If there will be no DI then remove injects and static and instantiate the object with dependencies.
    @Inject
    private readonly IInterfaceA _a;

    @Inject
    private readonly IInterfaceB _b;

    /* made the class as static so as you said we will be using a DI container.
    public ReminderFactory(IInterfaceA a, IInterfaceB b) {
       _a = a; 
       _b = b;
    }
    */

    public IReminderStrategy getReminder(String messageType) {
       switch case(messageType)
       {
          IReminderStrategy strategy;
          case "invite":
             strategy = new InviteReminder(_a, _b)
             break;
          case "book":
             strategy = new BookingReminder(_a, _b)
             break; 
       }         
    }
}

1)实例化和传递策略(用于教学目的,即清楚地说明。)

然后在客户端的某个地方和一步之前:

IReminderStrategy reminderStrategy = ReminderFactory.getReminder("invite");
shopService.shop(reminderStrategy);

最后在客户端:

public class ShopService {
   public void shop(IReminderStrategy reminderStrategy) {
      reminderStrategy.GenerateReminders("taha");
   }
}

2)或直接:

public class ShopService {
   public void shop() {
      //...
      IReminderStrategy reminderStrategy = ReminderFactory.getReminder("invite");
      reminderStrategy.GenerateReminders("taha");
      //...
   }
}

并且可能在另一项服务中:

public class TravelService myService() {
   public void travel() {
      //travel preparation
      IReminderStrategy reminderStrategy = ReminderFactory.getReminder("book");
      reminderStrategy.GenerateReminders("admin");
      //other travel things or maybe do something with the result.;
   }
}

推荐阅读