C#使用策略模式的正确方法

时间:2020-01-09 13:07:04

标签: c# design-patterns

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

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

但是要使用类似下面的内容。但不确定如何在切换情况下传递参数来设置策略。使用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;          
    }
}

3 个答案:

答案 0 :(得分:0)

您的上下文类(ExampleService)不应意识到特定行为(策略)有不同的实现。而不是由上下文类负责实例化策略,而是应将策略作为其依赖项传递。这样,您就可以实现松散耦合,因为实例化可能取决于上下文类范围之外的许多因素,并且可能也相当复杂。它还允许您将来添加更多策略,而无需修改ExampleService

public class ExampleService 
{
    private readonly IReminderStrategy strategy;

    public ExampleService(IReminderStrategy strategy)
    {
        this.strategy = strategy;
    }
}

应将提供哪种策略类型的决定委托给IoC容器。像

if (useA)
{
    // bind IReminderStrategy to StrategyA
}
else
{
    // bind IReminderStrategy to StrategyB
} 

答案 1 :(得分:0)

您将需要一个以上的类(ConcreteClass)来实现接口方法,并将您的对象(StrategyA或StrategyB)作为参数传递给新的此类对象(ConcreteClass),然后在需要时调用该方法。

switch (message)
        {
            case "A":
                concreteObject.SampleMethod(new StrategyA());
                break;
            case "B":
                concreteObject.SampleMethod(new StrategyB());
                break;
            default:                    
                break;
        }
.... 
concreteObject.Execute(inputMessage)

class Concrete
{
    IReminderStrategy _reminderStrategy;
    public void SampleMethod(IReminderStrategy reminderStrategy)
    {
        _reminderStrategy = reminderStrategy
    }

    public void Execute(string message)
    {
        _reminderStrategy.GenerateReminders(message);
    }
}

答案 2 :(得分:0)

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

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.;
   }
}