Sas*_*sky 18 .net c# oop duck-typing factory-pattern
我有2个班:
public class Articles
{
private string name;
public Articles(string name)
{
this.name = name;
}
public void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + name);
}
}
Run Code Online (Sandbox Code Playgroud)
和
public class Questionnaire
{
private string name;
public Questionnaire(string name)
{
this.name = name;
}
public void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + name);
}
}
Run Code Online (Sandbox Code Playgroud)
我想写一个方法,它取一个整数(1表示Articles应该返回,2表示意思Questionnaire)和一个名字.
此方法必须返回这两个类之一的实例:
public [What type??] Choose(int x, string name)
{
if (x == 1)
{
Articles art = new Articles(name);
return art;
}
if (x == 2)
{
Questionnaire ques = new Questionnaire(name);
return ques;
}
}
Run Code Online (Sandbox Code Playgroud)
我应该使用什么返回类型,所以我可以调用Output()结果?
Dar*_*ren 27
为什么没有已定义的基类Output.然后返回基地.
public abstract class BaseType {
public abstract void Output();
}
Run Code Online (Sandbox Code Playgroud)
双方Articles并Questionaire应该继承这个BaseType.
public class Articles : BaseType {
// Output method here
}
public class Questionaire : BaseType {
// Output method here
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
public static BaseType Choose(int x, string name)
{
if (x == 1)
{
Articles art = new Articles(name);
return art;
}
if (x == 2)
{
Questionnaire ques = new Questionnaire(name);
return ques;
}
}
Run Code Online (Sandbox Code Playgroud)
你也可以通过一个来实现这个目标interface.
public interface IInterface {
void Output();
}
public class Articles : IInterface {
// Output method here
}
public class Questionaire : IInterface {
// Output method here
}
Run Code Online (Sandbox Code Playgroud)
然后,您必须修改Choose方法以返回IInterface而不是BaseType.无论你选择哪一个都取决于你.
注意:即使您无法更改原始类,仍然可以使用这些方法,然后dynamic提供实现该接口的包装类,并将原始或转发调用继承到相应的方法:
public class ArticlesProxy : Articles, IInterface
{
public ArticlesProxy(string name) : base(name){}
}
public class QuestionaireProxy : Questionaire, IInterface {
Questionaire inner;
public QuestionaireProxy(string name) { inner = new Questionaire(name); }
public void Output() { inner.Output();}
}
Run Code Online (Sandbox Code Playgroud)
Mik*_*oud 15
这样的事情怎么样:
public interface IHasOutput
{
void Output();
}
public class Articles : IHasOutput
public class Questionnaire : IHasOutput
Run Code Online (Sandbox Code Playgroud)
然后:
public static IHasOutput Choose...
Run Code Online (Sandbox Code Playgroud)
您当然可以将您的界面称为您想要的任何内容,除此之外IHasOutput,我只是不知道该怎么称呼它.这就是接口的用途.共享公共接口的两种不同的具体实现.现在,当你打电话时,你可以这样做:
var entity = MyClass.Choose(1, "MyName");
entity.Output();
Run Code Online (Sandbox Code Playgroud)
并且返回具体实现并不重要.你知道它实现了一个通用的接口.
这里提供的答案很棒,但我不喜欢的一个参数x是选择应该创建的类型.这创造了魔法数字的使用,即使对你来说也可能变得头疼.
你可以在这里利用泛型,即make方法 Choose:
public static T Choose<T>(string name)
// type constraint to ensure hierarchy.
where T : BaseClass // BaseClass have common functionality of both class.
{
// Unfortunately you can't create instance with generic and pass arguments
// to ctor. So you have to use Activator here.
return (T)Activator.CreateInstance(typeof(T), new[] { name });
}
Run Code Online (Sandbox Code Playgroud)
用法:
Articles article = ClassWithChooseMethod.Choose<Articles>("name");
Questionnaire questionnaire = ClassWithChooseMethod.Choose<Questionnaire>("name2");
Run Code Online (Sandbox Code Playgroud)
编辑
正如@ OlivierJacot-Descombes在评论x中提到的,选择类型可能是用户输入的.在这种情况下,您可以创建enum相应的值:
enum ArticleType {
Articles = 1,
Questionnaire = 2
}
Run Code Online (Sandbox Code Playgroud)
并有超载Choose:
public static BaseClass Choose(ArticleType type, string name) {
switch (type) {
case ArticleType.Articles:
return ClassWithChooseMethod.Choose<Articles>(name);
case ArticleType.Questionnaire:
return ClassWithChooseMethod.Choose<Questionnaire>(name);
default:
return default(BaseClass);
}
}
Run Code Online (Sandbox Code Playgroud)
和用法:
var obj = ClassWithChooseMethod.Choose((ArticleType)userInput, "some name");
Run Code Online (Sandbox Code Playgroud)
这使您可以保持代码更清洁,并有助于将来的维护(例如,您可以更改类创建的逻辑Choose).
PS您可能有兴趣了解有关工厂模式的更多信息.
| 归档时间: |
|
| 查看次数: |
9311 次 |
| 最近记录: |