共享多级功能的最佳实践

时间:2012-02-26 15:10:50

标签: c# oop design-patterns

过去我曾经多次经历过这种商业行为,而这一次决定在这里发帖提问,因为我很好奇其他人是如何实施的。

我的系统中有四个进程。每个进程表示为一个类(在C#环境中),由该进程专用的共享功能和功能组成。

这是我系统的类层次结构:

             BASE
            /     \
           A       B
          / \     / \
        Ax  Ay   Bx   By

BASE,A和B是抽象类,包含抽象方法和实际实现 Ax,Ay,Bx和By是表示过程的类。每个类都有其独特的方法,以及与其他进程共享的方法。例如,Ax有自己的方法,它与Ay和Bx共享方法。所有类共享的附加功能都在BASE中实现。

准确地说:
Ax类与Ay通过A类共享相同的方法(实际实现)。所以Bx用By via B class分享它的方法。

除此之外,Ax与Bx共享另一部分方法。以同样的方式,Ay与By共享相同的方法。这是通过BASE类完成的。问题是每个类都暴露在他们不应该注意的功能中。例如,Ax不应该知道Ay和By之间共享的方法。

我怎样才能设计出更好的系统实现?是否有任何旨在简化此设置的设计模式?

5 个答案:

答案 0 :(得分:2)

您的问题被称为组合爆炸。

使用合成比继承更好。像策略patern或也许Decorator(取决于你的问题的细节)。例如:

interface IBigLetterStrategy { /*some methods common for A and B*/ }
class A : IBigLetterStrategy { /* impl */ }
class B : IBigLetterStrategy { /* impl */}

interface ISmallLetterStrategy { /*some methods common for x and y*/ }
class x : ISmallLetterStrategy { /* impl */ }
class y : ISmallLetterStrategy { /* impl */ }

最后:

class Process
{
    IBigLetterStrategy bigLetter;
    ISmallLetterStrategy smallLetter;
    /*unique logic here*/
}

答案 1 :(得分:2)

如果我理解你的问题,简单地声明公共接口将不起作用,因为你需要一个共享的实现,而不仅仅是一个共享的结构。

由于您需要共享实现,因此该实现实际上是共享依赖项。您正在寻找的是简单的依赖性反转:将共享行为移到另一个类并调用该类。

让我们让你的例子更具体:

         Animal
          /  \
   Mammal    Insect
    /  \        /  \
  Bat  Cat    Bee  Grasshopper

为了这个例子的目的,假设:

  • 蝙蝠和蜜蜂可以飞,但不能跳。
  • 猫和蚱蜢可以跳,但不会飞。
  • 这些是众所周知的事实(即使它们错了:)。)。

还假设跳线以相同的方式跳跃,并且飞行员以同样的方式飞行。这是实现它的一种方法:

  1. 为Flight和Jumping添加分别具有Fly()和Jump()方法的实现类。
  2. 创建IFlier和IJumper接口并将它们与正确的动物相关联(这是可选的)。
  3. 将Jumping对象传递给IJumper构造函数(Cat和Grasshopper)。
  4. 将Flight对象传递给IFlier构造函数(Bat和Bee)。
  5. 这看起来像是:

    为了让这个工作,动物将不得不称之为实施:

    public class Bat : Mammal, IFlier
    {
        private readonly IFlight _flight;
    
        public Bat(Flight flight)
        {
            _flight = flight;
        }
    
        public void Fly() // implements IFlier.Fly()
        {
            _flight.Fly();
        }
    }
    

    毋庸置疑,其他动物的实施方式也是类似的。使用它非常简单:

    var flight = new Flight();
    var jumping = new Jumping();
    
    IFlier bat = new Bat(flight);
    IJumper cat = new Cat(jumping);
    IFlier bee = new Bee(flight);
    IJumper grasshopper = new Grasshopper(jumping);
    
    bat.Fly();
    cat.Jump();
    bee.Fly();
    grasshopper.Jump();
    

    您也可以在Animal上创建一个公共抽象方法Travel(),它会根据需要调用_flight.Fly()或_jumping.Jump()方法,而不是使用IFlier和IJumper接口。这实际上取决于你的需求。

    总结一下:

    • 使用依赖性倒置。
    • 提取常见行为并将它们移动到作为依赖项传递给需要它们的实现的类。

    希望有所帮助。

答案 2 :(得分:1)

听起来我的课程不够小(违反SOLID)并且你的关系不是真正is-a。这通常会导致所描述的问题(至少对我而言)。

始终尝试使用合成而不是继承。

如果您想要更详细的答案,请添加更详细的代码。

答案 3 :(得分:0)

您可以使用Interfaces控制基类中方法的曝光。这称为适配器模式,请参阅问题How to hide (remove) a base class's methods in C#?

答案 4 :(得分:-2)

如果你有Ax和Bx共享的方法,你可以考虑另一个抽象类X来包含它们,并使用多重继承将它包含在Ax和Bx中。