2

我目前正在开发一个机器人,并且有大约 8 个用于不同对话框的单独类(都在同一个命名空间中!)。它们都包含不同的任务,因此我遇到了一个小问题。我想知道最佳实践是什么:使用接口,使用工厂模式……然而,所有这些选项都迫使我使用内部方法。(我通过接口得到它,因为你承诺某些行为,但是对于工厂模式我真的不知道 - 老实说......)因为没有特定方法的定义 - 但这意味着我必须做出很多这些内部方法,我试图避免冗余。

首先我只是实例化了一个新对象,但我很快意识到这意味着每次调用机器人时都会创建一个各种类型/对话框的新对象——这不是很有效,对吧?我也尝试在构造函数中实例化它们,但这迫使我使用接口,这给我带来了与我之前所说的相同的问题。我也研究了部分类,但我不确定使用 8 个部分类是否真的......好吗?

现在我正在用这段代码尝试工厂模式:(感谢这个线程:How to prevent an instance of an object in c#

public class DialogFactory
    {
        private NameDialog _nameDialog;
        private CertificateDialog _certificateDialog;
        private ProfileDialog _profileDialog;
        private ClassDialog _classDialog;
        private LocationDialog _locationDialog;
        private SkillDialog _skillDialog;
        private EducationDialog _educationDialog;
        private SpecializationDialog _specializationDialog;

        public DialogFactory CreateDialog(string dialog)
        {
            switch (dialog.ToLower())
            {
                case "name": return new NameDialog();
                case "certificate": return new CertificateDialog();
                case "profile": return new ProfileDialog();
                case "class": return new ClassDialog();
                case "location": return new LocationDialog();
                case "skill": return new SkillDialog();
                case "education": return new EducationDialog();
                case "specialization": return new SpecializationDialog();
                default: throw new Exception("That dialog does not exist.");
            }

            throw new Exception("That dialog does not exist.");
        }
    }

为了给出对话框看起来的一些上下文,我还将在此处添加名称对话框:

public class NameDialog : DialogFactory
    {
        ProfileService profileService = new ProfileService();

        public async Task AddNameResponse(ITurnContext turnContext, Profile profile, string value { … }
     }

我尝试在主方法中访问 AddNameResponse 任务,如下所示:await dialog.CreateDialog("name").AddNameResponse(turnContext, profile, value);这不被接受,但是给了我以下警告:“DialogFactory”不包含“AddNameResponse”的定义,并且没有可访问的扩展方法“AddNameResponse”接受第一个参数'对话工厂'。修复将是一个内部任务,但我试图避免这种情况(之前给出的原因)。

我真的很茫然,因为我不知道最佳做法是什么。我正在尝试制作我可以制作的最有效和最干净的代码,并避免冗余并尽可能多地使用松散耦合 - 但我不知道如何在这种情况下实现这一点......我希望我已经制定了我的问题足够好(也是问题)!

4

1 回答 1

2

工厂模式对于多态是有意义的。这意味着,例如,我们想要一个IDialog并且我们不在乎实现是什么。我们不想知道。这样,我们的代码依赖于IDialog并且不耦合到任何实现它的特定类。

如果您尝试这样做:

dialog.CreateDialog("name").AddNameResponse(turnContext, profile, value);

...错误是返回的任何内容都dialog.CreateDialog("name")没有AddNameResponse方法,这表明您的代码依赖于一些比工厂返回的更具体的类。

工厂不会减少耦合有几个原因:

  • 您的代码仍然依赖于NameDialog. 你需要那个确切的类和它的AddNameResponse方法。
  • 即使工厂返回了那个确切的类,现在你也耦合到了工厂那个类。

你想减少耦合是有道理的,因为如果一个类被绑定到NameDialog它也被绑定到ProfileService. 测试一个依赖于的类NameDialog而不依赖于 是不可能的ProfileService

潜在的解决方案将涉及更改依赖于NameDialog. 这里有几个想法:

  • 定义一个描述您的类需要做什么的抽象(例如接口或委托)NameDialog。将其注入您的班级。现在你的类依赖于抽象,而不是具体的类。
  • 如果NameDialog做了一些非常简单的事情,也许你可以注入它而不是抽象,更好的解决方法是定义一个抽象来表示ProfileService并将其注入NameDialog.
  • 可能两者都做。

这些都意味着你是

  • 通过依赖抽象来避免耦合
  • 让您的依赖注入/IoC 容器负责创建对象

这比将所有这些对象的创建组合到一个工厂中效果更好。这种方法只有在工厂返回的任何对象都可以替代任何其他类型时才有意义——您不需要知道具体类型是什么。

于 2019-05-20T14:04:28.937 回答