将教程的逻辑与主应用程序逻辑分离

时间:2018-08-15 10:13:11

标签: c# solid-principles object-oriented-analysis

在这里,我们正在开发具有特定UI的电子邮件客户端软件,我们需要将其教给用户。

有一些类可以处理应用程序的逻辑。例如,在项目的主要类别之一中就有这样的功能:

public void ComposeMessage(string username,string message)
{
    MessageComposer.ComposeMessage(username, message);
}

因此,在上述功能中,我们向用户发送了一条消息。

,但在应用程序的另一侧;有一个辅导阶段。因此,当用户进入应用程序的教程端时,他可以与我们告诉他的应用程序按钮进行交互,但是我们不想发送真实的消息。所以我们像这样改变了上面的功能:

public void ComposeMessage(string username,string message)
{
    if(!Global.IsTutorial)
        MessageComposer.ComposeMessage(username, message);
}

因此,我们在其主体中添加了许多功能 if(!Global.IsTutorial) 。我们如何避免这种情况?我们不想在教程部分中更改函数的主体,也不想在我们的项目中添加更多的代码和类。我们希望将更改保持在最低水平。

1 个答案:

答案 0 :(得分:3)

有很多方法可以实现您想要的,但是所有这些都暗示着,首先,您不直接使用ComposeMessage,而是为其创建接口并重构调用方以将其作为依赖项注入:

public interface IMessageComposer
{
    void ComposeMessage(string username, string message);
}

public class MyApp
{
    IMessageComposer messageComposer;

    public MyApp(IMessageComposer messageComposer)
    {
        this.messageComposer = messageComposer;
    }

    public void Foo()
    {
        messageComposer.ComposeMessage(username, message);
    }
}

当您不依赖具体的实现并注入依赖项时,可以将IMessageComposer的实现更改为所需的内容,而无需实际触摸原始的MessageComposerMyApp的代码。

例如,您可以像这样创建TutorialMessageComposer

public class TutorialMessageComposer : IMessageComposer
{
    public void ComposeMessage(string username, string password)
    {
        Console.WriteLine("Tutorial mode!");
    }
}

RoutingMessageComposer装饰器将检查当前模式并调用正确的作曲器

public class RoutingMessageComposer : IMessageComposer
{
    IMessageComposer composer;
    IMessageComposer tutorialComposer;

    public RoutingMessageComposer(IMessageComposer composer, IMessageComposer tutorialComposer)
    {
        this.composer = composer;
        this.tutorialComposer = tutorialComposer;
    }

    public void ComposeMessage(string username, string message)
    {
        if (Global.IsTutorial)
            tutorialComposer.ComposeMessage(username, message);
        else
            composer.ComposeMessage(username, message);    
    }
}

所有准备工作完成后,您只需将RoutingMessageComposer插入MyApp

var app = new MyApp(new RoutingMessageComposer(new MessageComposer(), new TutorialMessageComposer()));