可以避免(很多)内部方法吗? (接口、工厂模式)
Are (a lot of) internal methods avoidable? (interface, factory pattern)
我目前正在开发一个机器人,并且有大约 8 个独立的 类 用于不同的对话框(都在同一个命名空间中!)。它们都包含不同的任务,因此我 运行 遇到了一个小问题。
我想知道最佳实践是什么:使用接口、使用工厂模式……然而,所有这些选项都迫使我使用内部方法。 (我用接口得到它,因为你承诺某些行为,但我真的不知道工厂模式 - 老实说......)因为没有特定方法的定义 - 但这意味着我必须很多这些内部方法,我正在努力避免冗余。
首先我只是实例化了一个新对象,但我很快意识到这意味着每次调用机器人时都会为每个 kind/dialog 创建一个新对象 - 这不是很有效吗?我还尝试在构造函数中实例化它们,但这迫使我使用接口,这给我带来了与我之前提到的相同的问题。我也研究过 partial 类 但我不确定使用 8 partial 类 是否真的..好吗?
现在我正在用这段代码尝试工厂模式:
(此线程的积分: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' 不包含 [=27= 的定义] 并且没有可访问的扩展方法 'AddNameResponse' 接受 'DialogFactory' 的第一个参数。修复将是一个内部任务,但我试图避免这种情况(之前给出的原因)。
我真的很茫然,因为我不知道最佳做法是什么。我正在尝试编写我能编写的最高效、最干净的代码,避免冗余并尽可能多地使用松散耦合——但我不知道在这种情况下如何做到这一点……
我希望我已经很好地阐述了我的问题(以及问题)!
工厂模式对多态性有意义。这意味着,例如,我们想要一个 IDialog
而我们不关心实现是什么。我们不想知道。这样我们的代码就依赖于 IDialog
并且不会耦合到实现它的任何特定 class。
如果您尝试这样做:
dialog.CreateDialog("name").AddNameResponse(turnContext, profile, value);
...错误是从 dialog.CreateDialog("name")
返回的任何内容都没有 AddNameResponse
方法,这表明您的代码依赖于一些比 class 更具体的方法什么是从工厂退回的。
工厂不会降低耦合有几个原因:
- 您的代码仍然依赖于
NameDialog
。您需要精确的 class 及其 AddNameResponse
方法。
- 即使工厂返回那个 class,现在您已耦合到 和 class.
的工厂
减少耦合是有道理的,因为如果 class 绑定到 NameDialog
,它也会绑定到 ProfileService
。在不依赖 ProfileService
.
的情况下,不可能测试依赖于 NameDialog
的 class
潜在的解决方案将涉及更改依赖于 NameDialog
的 classes。以下是一些想法:
- 定义一个抽象(例如接口或委托)来描述您的 class 需要用
NameDialog
做什么。将其注入您的 class。现在你的 class 取决于抽象,而不是具体的 class.
- 如果
NameDialog
做了一些非常简单的事情,也许你可以注入它而不是抽象,更好的解决方法是定义一个表示 ProfileService
的抽象并将其注入 NameDialog
.
- 可能两者都做。
每一个都意味着你是
- 通过依赖抽象避免耦合
- 将创建对象的责任交给你的依赖项injection/IoC容器
这比将所有这些对象的创建合并到一个工厂中效果更好。这种方法只有在工厂返回的任何对象可替代任何其他类型时才有意义——您不需要知道具体类型是什么。
我目前正在开发一个机器人,并且有大约 8 个独立的 类 用于不同的对话框(都在同一个命名空间中!)。它们都包含不同的任务,因此我 运行 遇到了一个小问题。 我想知道最佳实践是什么:使用接口、使用工厂模式……然而,所有这些选项都迫使我使用内部方法。 (我用接口得到它,因为你承诺某些行为,但我真的不知道工厂模式 - 老实说......)因为没有特定方法的定义 - 但这意味着我必须很多这些内部方法,我正在努力避免冗余。
首先我只是实例化了一个新对象,但我很快意识到这意味着每次调用机器人时都会为每个 kind/dialog 创建一个新对象 - 这不是很有效吗?我还尝试在构造函数中实例化它们,但这迫使我使用接口,这给我带来了与我之前提到的相同的问题。我也研究过 partial 类 但我不确定使用 8 partial 类 是否真的..好吗?
现在我正在用这段代码尝试工厂模式: (此线程的积分: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' 不包含 [=27= 的定义] 并且没有可访问的扩展方法 'AddNameResponse' 接受 'DialogFactory' 的第一个参数。修复将是一个内部任务,但我试图避免这种情况(之前给出的原因)。
我真的很茫然,因为我不知道最佳做法是什么。我正在尝试编写我能编写的最高效、最干净的代码,避免冗余并尽可能多地使用松散耦合——但我不知道在这种情况下如何做到这一点…… 我希望我已经很好地阐述了我的问题(以及问题)!
工厂模式对多态性有意义。这意味着,例如,我们想要一个 IDialog
而我们不关心实现是什么。我们不想知道。这样我们的代码就依赖于 IDialog
并且不会耦合到实现它的任何特定 class。
如果您尝试这样做:
dialog.CreateDialog("name").AddNameResponse(turnContext, profile, value);
...错误是从 dialog.CreateDialog("name")
返回的任何内容都没有 AddNameResponse
方法,这表明您的代码依赖于一些比 class 更具体的方法什么是从工厂退回的。
工厂不会降低耦合有几个原因:
- 您的代码仍然依赖于
NameDialog
。您需要精确的 class 及其AddNameResponse
方法。 - 即使工厂返回那个 class,现在您已耦合到 和 class. 的工厂
减少耦合是有道理的,因为如果 class 绑定到 NameDialog
,它也会绑定到 ProfileService
。在不依赖 ProfileService
.
NameDialog
的 class
潜在的解决方案将涉及更改依赖于 NameDialog
的 classes。以下是一些想法:
- 定义一个抽象(例如接口或委托)来描述您的 class 需要用
NameDialog
做什么。将其注入您的 class。现在你的 class 取决于抽象,而不是具体的 class. - 如果
NameDialog
做了一些非常简单的事情,也许你可以注入它而不是抽象,更好的解决方法是定义一个表示ProfileService
的抽象并将其注入NameDialog
. - 可能两者都做。
每一个都意味着你是
- 通过依赖抽象避免耦合
- 将创建对象的责任交给你的依赖项injection/IoC容器
这比将所有这些对象的创建合并到一个工厂中效果更好。这种方法只有在工厂返回的任何对象可替代任何其他类型时才有意义——您不需要知道具体类型是什么。