设计模式使用而不是多重继承

Miz*_*zor 23 language-agnostic oop design-patterns

来自C++背景,我习惯了多重继承.我喜欢瞄准我脚的霰弹枪的感觉.如今,我在C#和Java中工作得更多,你只能继承一个基类但实现任意数量的接口(我的术语是否合适?).

例如,让我们考虑两个实现公共接口但不同(但需要)基类的类:

public class TypeA : CustomButtonUserControl, IMagician
{
    public void DoMagic()
    {
        // ...
    }
}

public class TypeB : CustomTextUserControl, IMagician
{
    public void DoMagic()
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这两个类都是UserControls所以我不能替换基类.两者都需要实现这个DoMagic功能.我现在的问题是该函数的两个实现都是相同的.我讨厌复制粘贴代码.

(可能的)解决方案:

  1. 我自然希望TypeATypeB共享一个共同的基类,在那里我只能写一次相同的函数定义.但是,由于只有一个基类的限制,我无法在层次结构中找到适合的位置.
  2. 人们也可以尝试实现一种复合模式.将DoMagic函数放在一个单独的帮助器类中,但这里的函数需要(并修改)相当多的内部变量/字段.将它们全部作为(参考)参数发送只会看起来很糟糕.
  3. 我的直觉告诉我,适配器模式可以在这里有一个位置,一些类在必要时在两者之间进行转换.但它也感觉很hacky.

我用语言无关来标记它,因为它适用于使用这种one-baseclass-many-interfaces方法的所有语言.

另外,请指出我是否误解了我提到的任何模式.

在C++中,我只使用私有字段创建一个类,该函数实现并将其放在继承列表中.什么是C#/ Java之类的正确方法?

Din*_*nah 10

您可以使用策略模式或类似的东西使用具有(组成),而不是一个(继承):

public class TypeA : CustomButtonUserControl, IMagician {
    IMagician magicObj = new Magical();
    public void DoMagic() {
        magicObj.DoMagic();
    }
}

public class TypeB : CustomButtonUserControl, IMagician {
    IMagician magicObj = new Magical();
    public void DoMagic() {
        magicObj.DoMagic();
    }
}

public class Magical : IMagician {
    public void DoMagic() {
        // shared magic
    }
}
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以实例化您的私有IMagician成员(例如通过构造函数将它们作为参数传递),但上面的内容应该让您开始.


Pat*_*her 9

  • 在.Net中,您可以将扩展方法应用于接口.在可能的情况下它非常简洁,适用于您,因为这是将常见实现应用于接口的一种罕见方式.当然要考虑它,但它可能对你不起作用,因为你说它DoMagic适用于很多私人成员.你可以打包这些私有变量internal吗?这样,扩展方法可以访问它们.
  • 在另一个类中具有通用功能.如果有一个合理的位置来放置这个通用功能,将对象传递给另一个类方法(也许这是UI功能,你已经有了一个UI助手......).再次,您可以使用内部/公共属性公开私有数据吗?(安全/封装当然是一个问题.我不知道你的课程是仅供内部使用还是公开展示.)
  • 否则,将单独的功能类(或特定函数指针)传递给接口定义的方法.你必须有一些重复的代码将你的私有变量传递给这个外部函数引用,但至少它不会太多,你的实现将在一个地方.
  • 我们可能会让这太复杂了.当你今晚入睡时,它不会让你觉得所有面向对象,但是你可以在你的图书馆里有一个所有IMagician实施者所称的静态例程吗?
  • 最后,适配器可能确实是您正在寻找的.不太可能但仍值得考虑的是Decorator模式.

如果没有显得特别好,选择什么样的感觉最好,用它几次,并重新安排明天.:)