过去我曾经多次经历过这种商业行为,而这一次决定在这里发帖提问,因为我很好奇其他人是如何实施的。
我的系统中有四个进程。每个进程表示为一个类(在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之间共享的方法。
我怎样才能设计出更好的系统实现?是否有任何旨在简化此设置的设计模式?
答案 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
为了这个例子的目的,假设:
还假设跳线以相同的方式跳跃,并且飞行员以同样的方式飞行。这是实现它的一种方法:
这看起来像是:
为了让这个工作,动物将不得不称之为实施:
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中。