混凝土类型或界面?
我有以下用例,很多代码紧密耦合在一个具体类型上(比如Concrete1)。后来想出了具体的类型需要改变,所以定义了一个接口。例如混凝土类型或界面?
Class ABC {
virtual int foo() = 0;
virtual int getType() = 0;
}
class Concrete1 : public ABC {
int foo() {
... }
int getType() {
return 1;
}
}
class Concrete2 : public ABC {
int foo() {
... }
int getType() {
return 2;
}
}
静态工厂模式用于创建对象。因此,创建对象新建Concrete1的所有地方都被替换为ABCFactory :: createType()。
现在代码中有很多地方需要检查createType返回的对象是否是Concrete1或者Concrete2并相应地执行相关逻辑(因此很多代码中的其他内容:():
我想避免在代码中有很多的if else作为这种变化的一部分。有什么建议?
这困扰了我很多的事情是
if (abc.getType() == 1) {
...
} else if (abc.getType() ==2) {
...
}
使用接口的全部要点是,您可以使用多态,这意味着您不必检查实例是什么类型。这样做是一个非常大的代码味道(请参阅Fowlers Refacotring)。移动条件逻辑的具体类,并添加TE功能,将它处理到接口
编辑(添加的代码示例,因为最初的职位是由手机完成):
你正在尝试做的:
void Main(string[] args)
{
Bird bird = BirdFactory.GetPigeon();
if (bird.GetType().Equals(typeof(Duck)))
{
Console.WriteLine("quack");
}
else if (bird.GetType().Equals(typeof(Pigeon)))
{
Console.WriteLine("coo coo");
}
}
相反,尝试:
interface Bird
{
void Speak();
}
class Duck : Bird
{
void Speak()
{
Console.Write("quack");
}
}
class Pigeon : Bird
{
void Speak()
{
Console.Write("coo coo");
}
}
void Main(string[] args)
{
Bird bird = BirdFactory.GetPigeon();
bird.Speak();
}
可以移动的地方,你正在检测类之外的对象类型班上?这种方式的功能(显然取决于具体的类)实际上是与相应的类相关联的吗?
如果你检查和/或在运行时切换类型,你可能要考虑使用运行时类型Informati如果它可用于您的编译器。它确实会增加一些开销,但它可以在不创建或维护自定义方法的情况下完成您要做的工作。
与纯粹主义者不同,我并不是真的“把功能放在课堂上,所以你可以使用多态性来解决类型切换问题”。尽管这两种方法都是有效的方法(虽然“在课堂上”的方法并不总是可行的,并且/或者在概念上是干净的)。
切换类型的原因在于,它会很快增加代码的复杂性并快速降低可维护性。当你开始打开类型时,你最终将开关放在你的代码中,如果有什么改变,现在你有很多地方可以改变 – IAmCodeMonkey 2009-01-03 01:36:59
通过与其他答案的协议,我觉得至少if/else块中的一些代码需要作为新的虚拟函数在具体类中移动。这将允许您利用多态性而不是使用自制反射模式来切换类型。
把...
另一个虚拟方法里面执行:
if (abc.getType() == 1) {
... // A
} else if (abc.getType() == 2) {
... // B
}
认沽A和B是这样的:
class ABC {
virtual int foo() = 0;
virtual void doIt() = 0; // choose a proper name
};
class Concrete1 : public ABC {
int foo() {
... }
void doIt() {
... // A
}
};
class Concrete2 : public ABC {
int foo() {
... }
void doIt() {
... // B
}
};
,改变你如果到
abc.doIt();
由于另一个人说,这正是动态调度的要点!除了更简洁之外,它也永远不会“忘记”处理类型。做你的开关,你可以默默无闻地处理某种特定的类型,因为当你引入一个新的实现时,你错过了更新那个地方的代码。还请记住在ABC中有一个虚拟析构函数。
+1表示良好的变量名称。它比foos和酒吧更容易理解。 – 2009-09-05 04:10:01