(很多)内部方法可以避免吗? (界面,工厂模式)

时间:2019-05-20 08:46:20

标签: c# interface factory-pattern redundancy internal-class

我目前正在使用漫游器,并且为不同的对话框提供了大约8个单独的类(都在同一个命名空间中!)。它们都包含不同的任务,因此我遇到了一个小问题。 我想知道最佳实践是什么:使用接口,使用工厂模式…但是,所有这些选项都迫使我使用内部方法。 (而且我通过接口实现了该功能,因为您承诺了某些行为,但是我实际上并不知道使用工厂模式-坦白地说。)因为没有为特定方法定义-但这意味着我必须做出这些内部方法很多,我正在努力避免重复。

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

现在我正在尝试使用以下代码的工厂模式: (该线程的积分:How to prevent an instantiation 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”接受“ DialogFactory”的第一个参数。该修补程序将是一个内部任务,但我正在尝试避免这种情况(前面给出的原因)。

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

1 个答案:

答案 0 :(得分: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容器负责创建对象

这比将所有这些对象的创建合并到一个工厂中更好。这种方法仅在工厂返回的任何对象可以替代任何其他类型的情况下才有意义-您不需要知道具体的类型是什么。