简体   繁体   English

在 C# 中实施策略设计模式的正确方法

[英]Correct way to implement strategy design Pattern in C#

I have a scenario wherein there are multiple conditions and I have to write a code in such a way that it should be open for extension and not for modification so I went with the strategy design pattern, below is my code, let me know if I'm on the correct path and need some guidance on the code written.我有一个场景,其中有多个条件,我必须以这样一种方式编写代码,即它应该对扩展开放而不是对修改开放,所以我采用了策略设计模式,下面是我的代码,如果我知道,请告诉我'在正确的道路上,需要一些关于编写代码的指导。

// Is this correct way to call it, how to apply dependency injection?
// You can find this code in the end
BaseOrderProcessing baseOrderProcessing =
    new BaseOrderProcessing(
        new BaseSubscribe(
            new SubscribeService(
                Subscribe)));  

Here is the actual code:这是实际的代码:

public interface IBaseOrderProcessing
{
    void ProcessOrder();
}

public class BaseOrderProcessing : IBaseOrderProcessing
{
    private IBaseOrderProcessing _baseOrderProcessing = null;
    public BaseOrderProcessing(IBaseOrderProcessing baseOrderProcessing)
    {
        _baseOrderProcessing = baseOrderProcessing;
    }
    public virtual void ProcessOrder()
    {
        _baseOrderProcessing.ProcessOrder();
    }
}

public interface ISubscribeService
{
    SubscribeType SubscribeType { get; set; }
    void ActivateSubscribe();

    void UpgradeSubscribe();
}

// Strategy Pattern 1  => Subscribe is one of the "if" condition
public class BaseSubscribe : IBaseOrderProcessing
{
    private ISubscribeService _SubscribeService = null;
    public BaseSubscribe(ISubscribeService SubscribeService)
    {
        _SubscribeService = SubscribeService;
    }
    
    public void ProcessOrder()
    {
        if (_SubscribeService.SubscribeType == SubscribeType.ACTIVATE)
            _SubscribeService.ActivateSubscription();

        if (_SubscribeService.SubscribeType == SubscribeType.UPGRADE)
            _SubscribeService.UpgradeSubscription();
        
    }
}

// Writing another class to simplify is correct ?????
public class SubscribeService : ISubscribeService
{
    private SubscribeDetails _Subscribedetails = null;

    public SubscribeType SubscribeType { get; set; }

    public SubscribeService(SubscribeDetails Subscribedetails)
    {
        _Subscribedetails = Subscribedetails;
        SubscribeType = Subscribedetails.SubscribeType;
    }
    public void ActivateSubscription()
    {
        // Code to save the Subscribe details in the database
        Console.WriteLine(
            $"\n\nSubscribe {_Subscribedetails.SubscribeId} for " +
            $"{_Subscribedetails.SubscribeName} activated for order Id: {_Subscribedetails.OrderId}" +
            $" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");        
    }      

    public void UpgradeSubscription()
    {
        // Code to upgrade the Subscribe details in the database
        Console.WriteLine(
            $"\n\nSubscribe {_Subscribedetails.SubscribeId} for " +
            $"{_Subscribedetails.SubscribeName} upgraded for order Id: {_Subscribedetails.OrderId}" +
            $" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");

    }
}  

Client code:客户端代码:

// Is this correct way to call it, how to apply dependency injection?
IBaseOrderProcessing baseOrderProcessing = null;
SubscribeDetails Subscribe = new SubscribeDetails();

Subscribe.OrderId = Guid.NewGuid();
Subscribe.SubscribeId = Guid.NewGuid();
Subscribe.SubscribeName = "Amazon";
Subscribe.SubscribeStartDate = DateTime.Now;
Subscribe.SubscribeEndDate = DateTime.Now.AddDays(30);
if (option == 1)
    Subscribe.SubscribeType = SubscribeType.ACTIVATE;

if (option == 2)
    Subscribe.SubscribeType = SubscribeType.UPGRADE;

baseOrderProcessing =
    new BaseOrderProcessing(
        new BaseSubscribe(
            new SubscribeService(
                Subscribe)));  

You are constructing object that requires runtime details in constructor and possibly (assumption from the post) shares a single common interface with other objects like itself - it's not great, but also not tragic - it just complicates things.您正在构建 object,它需要构造函数中的运行时详细信息,并且可能(帖子中的假设)与其他对象(例如它本身)共享一个公共接口——这不是很好,但也不是悲剧——它只会使事情复杂化。

You could apply builder / abstract factory pattern in addition and configure dependency injection to inject said builder / factory service, so that the client could resolve actually needed implementation based on some runtime data.您可以另外应用构建器/抽象工厂模式并配置依赖注入以注入所述构建器/工厂服务,以便客户端可以根据一些运行时数据解决实际需要的实现。

If possible, you could try to register this (BaseOrderProcessing) service completely from scratch in DI container and inject it as fully configured one if you do not have to resolve it based on some runtime input data but for example you are taking config from a json file while starting this app.如果可能,您可以尝试在 DI 容器中从头开始完全注册此 (BaseOrderProcessing) 服务,如果您不必根据某些运行时输入数据解析它,但例如您正在从 json 获取配置,则将其作为完全配置的服务注入启动此应用程序时的文件。

You could also redesign your service so that it will be injected as uninitialized and the SubscribeDetails will be given to it by some method - it would simplify DI configuration.您还可以重新设计您的服务,以便将其作为未初始化的注入,并通过某种方法将SubscribeDetails提供给它——这将简化 DI 配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM