Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 当使用多态性没有意义时,如何实现特定于类型的功能?_Oop_Design Patterns_Inheritance_If Statement_Polymorphism - Fatal编程技术网

Oop 当使用多态性没有意义时,如何实现特定于类型的功能?

Oop 当使用多态性没有意义时,如何实现特定于类型的功能?,oop,design-patterns,inheritance,if-statement,polymorphism,Oop,Design Patterns,Inheritance,If Statement,Polymorphism,OOP语言未被正确利用的常见危险信号如下所示: if (typeof(x) == T1) { DoSomethingWithT1(x); } else if (typeof(x) == T2) { DoSomethingWithT2(x); } IEnumerably<IBlahImplementor> blahImplementors; foreach (var implementor in blahImplementors) { blahImplemento

OOP语言未被正确利用的常见危险信号如下所示:

if (typeof(x) == T1)
{
    DoSomethingWithT1(x);
}
else if (typeof(x) == T2)
{
    DoSomethingWithT2(x);
}
IEnumerably<IBlahImplementor> blahImplementors;
foreach (var implementor in blahImplementors)
{
  blahImplementors.Add(implementor.ForType, implementor);
}
// interface used to add external functionality to pricing models
public interface PricingModelVisitor {
    void visitPricingModel1(PricingModel1 m);
    void visitPricingModel2(PricingModel2 m);
    ...
}
// your existing base-class, with added abstract accept() method to accept a visitor
public abstract class PricingModelBase {
    public abstract void accept(PricingModelVisitor v);
    ...
}
// concrete implementations of the PricingModelBase implement accept() by calling the 
// appropriate method on the visitor, passing themselves as the argument
public class PricingModel1 : PricingModelBase { 
    public void accept(PricingModelVisitor v) { v.visitPricingModel1(this); }
    ...
}
public class PricingModel2 : PricingModel {
    public void accept(PricingModelVisitor v) { v.visitPricingModel2(this); }
    ...
}
// concrete implementation of the visitor interface, in this case with the new 
// functionality of adding the appropriate controls to a parent control
public class ParameterGuiVisitor : PricingModelVisitor {
    private Control _parent;
    public ParameterGuiVisitor(Control parent) { _parent = parent; }
    visitPricingModel1(PricingModel1 m) {
        // add controls to _parent for PricingModel1
    }
    visitPricingModel2(PricingModel2 m) {
        // add controls to _parent for PricingModel1
    }
}
此类设计问题的标准“修复”是通过继承基类型或实现公共接口(使用支持它的语言),使
T1
T2
共享一个接口;例如,在C#中,解决方案可能是:

public interface IT
{
    void DoSomething();
}
但是,有时您希望实现基于对象类型而不同的功能,但该功能不属于该对象的类型;因此,多态性似乎是错误的方向

例如,考虑UI的情况,该UI提供给定数据块的视图。假设此视图能够根据显示的数据类型呈现各种布局和控件,那么在没有大量

if
/
else
语句的情况下,您将如何实现此特定于类型的呈现

出于我希望显而易见的原因,在这种情况下,将呈现逻辑放在类型本身中给我的印象是一个非常糟糕的决定。另一方面,如果不将数据对象的类型与其可视化表示耦合,我很难看到如何避免
if
/
else
场景

这里有一个具体的例子:我开发了一个交易应用程序,它对各种市场产品使用许多不同的定价模型。这些不同的模型由从公共
PricingModel
基继承的类型表示;每种类型都与一组完全不同的参数相关联。当用户想要查看特定定价模型(特定产品)的参数时,这些参数当前通过一个窗体显示,该窗体检测模型的类型并显示一组适当的控件。我的问题是如何比目前更优雅地实现它(使用一个大的
if
/
else
块)

我意识到这似乎是一个非常基本的问题;这只是我知识(坚实的OOP原则?设计模式?常识?)中的一个缺口,我认为是时候解决了。

我们正在按类型将(Spring.Net)这样的功能注入字典中

IDictionary<Type, IBlahImplementor> blahImplementors;

blahImplementors[thingy.GetType()].Do(thingy);
然后将其添加到字典中,如下所示:

if (typeof(x) == T1)
{
    DoSomethingWithT1(x);
}
else if (typeof(x) == T2)
{
    DoSomethingWithT2(x);
}
IEnumerably<IBlahImplementor> blahImplementors;
foreach (var implementor in blahImplementors)
{
  blahImplementors.Add(implementor.ForType, implementor);
}
// interface used to add external functionality to pricing models
public interface PricingModelVisitor {
    void visitPricingModel1(PricingModel1 m);
    void visitPricingModel2(PricingModel2 m);
    ...
}
// your existing base-class, with added abstract accept() method to accept a visitor
public abstract class PricingModelBase {
    public abstract void accept(PricingModelVisitor v);
    ...
}
// concrete implementations of the PricingModelBase implement accept() by calling the 
// appropriate method on the visitor, passing themselves as the argument
public class PricingModel1 : PricingModelBase { 
    public void accept(PricingModelVisitor v) { v.visitPricingModel1(this); }
    ...
}
public class PricingModel2 : PricingModel {
    public void accept(PricingModelVisitor v) { v.visitPricingModel2(this); }
    ...
}
// concrete implementation of the visitor interface, in this case with the new 
// functionality of adding the appropriate controls to a parent control
public class ParameterGuiVisitor : PricingModelVisitor {
    private Control _parent;
    public ParameterGuiVisitor(Control parent) { _parent = parent; }
    visitPricingModel1(PricingModel1 m) {
        // add controls to _parent for PricingModel1
    }
    visitPricingModel2(PricingModel2 m) {
        // add controls to _parent for PricingModel1
    }
}

您所描述的基本上就是应用程序的用例

编辑:对于您的具体示例,您可以像下面这样应用访问者模式:

if (typeof(x) == T1)
{
    DoSomethingWithT1(x);
}
else if (typeof(x) == T2)
{
    DoSomethingWithT2(x);
}
IEnumerably<IBlahImplementor> blahImplementors;
foreach (var implementor in blahImplementors)
{
  blahImplementors.Add(implementor.ForType, implementor);
}
// interface used to add external functionality to pricing models
public interface PricingModelVisitor {
    void visitPricingModel1(PricingModel1 m);
    void visitPricingModel2(PricingModel2 m);
    ...
}
// your existing base-class, with added abstract accept() method to accept a visitor
public abstract class PricingModelBase {
    public abstract void accept(PricingModelVisitor v);
    ...
}
// concrete implementations of the PricingModelBase implement accept() by calling the 
// appropriate method on the visitor, passing themselves as the argument
public class PricingModel1 : PricingModelBase { 
    public void accept(PricingModelVisitor v) { v.visitPricingModel1(this); }
    ...
}
public class PricingModel2 : PricingModel {
    public void accept(PricingModelVisitor v) { v.visitPricingModel2(this); }
    ...
}
// concrete implementation of the visitor interface, in this case with the new 
// functionality of adding the appropriate controls to a parent control
public class ParameterGuiVisitor : PricingModelVisitor {
    private Control _parent;
    public ParameterGuiVisitor(Control parent) { _parent = parent; }
    visitPricingModel1(PricingModel1 m) {
        // add controls to _parent for PricingModel1
    }
    visitPricingModel2(PricingModel2 m) {
        // add controls to _parent for PricingModel1
    }
}
现在,当您需要显示
PricingModelVisitor
的特定子类型的参数的编辑控件时,您可以简单地调用

somePricingModel.accept(new ParameterGuiVisitor(parentControl))

它将为您填充适当的GUI。

您可以在描述和命令模式时使用公共接口方法来触发“功能不属于该对象的类型”的方法。我认为这不会打破坚实的OOP原则。

访问者可能不够灵活。不能动态添加访问类型。您只能动态添加访问者的实现。您所说的“动态添加访问者类型”是什么意思?visitor模式允许您通过简单地向处理此新类型的visitor接口添加新方法来添加新类型。这将在编译时迫使您更新所有现有的visitor实现,以适当地处理此新类型,这在基于字典的解决方案中很容易被忽略。有时需要注入、轻松注册类型、在运行时添加类型,添加指定访问者界面的程序集不知道的类型等。我并不是说动态比静态好,我只是说对于这里描述的问题来说,它可能不够灵活。“有时它需要…”-问题中没有提到这些。