拥有一个派生自基类的类并且还包含它的实例是一个好的设计吗?

时间:2013-01-13 06:27:54

标签: c# oop class class-diagram

我正在设计一个基于生产者/消费者的应用程序,我一直坚持代表生产者在类表示中生成的任务。

实际问题如下:制作人可以制作StandaloneTask,可以直接由消费者使用,也可以产生CompressTask,必须首先通过TaskDecompressor它首先将其提取到一些StandaloneTask中,然后消费者可以使用它们。

由于StandaloneTaskCompressTask之间存在很多共性,因此我创建了一个名为TaskBase的基类,其中包含所有这些常见信息。

class abstract TaskBase 
{

}

class StandloneTaskType1: TaskBase
{

}

class StandloneTaskType2: TaskBase
{

}

.
.
.

class StandloneTaskTypeN: TaskBase
{

}

如何解压缩任务? 任务可以具有一个或多个需要在运行时填充的参数。压缩任务由具有参数的任务和有关如何获取需要填充这些参数的值的其他信息组成。获取值后,假设TaskDecompressor将所有这些值填充到参数化任务中以生成一个或多个独立任务。

我创建了一个CompressTask课程如下。

class CompressTask: TaskBase
{
    TaskBase task;

    //runtime parameters
}

现在,我看起来非常奇怪CompressTask来自TaskBase,它还包含TaskBase的实例。有这样的课程是否正确?或者是给定案例的更好的类表示。

4 个答案:

答案 0 :(得分:3)

总的来说,这种结构并不罕见,你有点开始走Composite pattern的道路。您的CompressTask有点像复合材料,而您的StandaloneTask就像Leaf。

我建议阅读该设计模式,并考虑让消费者更容易使用TaskBase的任何子类,无论它是CompressTask还是StandaloneTask。这将加强您的设计并简化消费。

答案 1 :(得分:1)

...想象

class Student: Person
{
    Person father;
    Person mother;
    Date dateOfEnrollment;
}

这完全没有意义吗?原则上你的CompressTask类没有任何问题。

答案 2 :(得分:0)

一个重要的面向对象设计规则:favor composition over implementation inheritance。仅仅因为StandaloneTaskCompressTask有许多共性并不能让它们成为共享相同基类的好选择。如果两个类共享某些接口,建议使用接口继承来排除接口因素。如果两个类共享某些实现,那么您最好将实现分解为某个类,并将其嵌入到上述两个类中(即组合)。

回到你的案例,CompressTask派生自TaskBase,它还包含一个TaskBase实例。这意味着您同时使用实现继承和组合,这并不是很好闻。以下骨架仅供您参考:

interface Task
{
    // some common Task interface here...
}

class TaskImpl
// Or: class TaskImpl : Task // depends on your needs
{    
    // some common Task-related implementation here...
}

class CompressTask: Task // interface inheritance, NOT implementation inheritance
{
    TaskImpl taskImpl; // contains *reusable* task-related implementation
    Task task;  // contains the target task(s) to be compressed
    // other code...
}

class StandloneTaskType1: Task
{
    TaskImpl taskImpl;
    // other code...
}

.
.
.

class StandloneTaskTypeN: Task
{
    TaskImpl taskImpl;
    // other code...
}

答案 3 :(得分:0)

更好......想象一下......

class Foo // implicitly extends Object
{
    String name; // also a direct subclass of Object (at least in Java anyway)
    Integer age; // extends Number, which extends Object (at least in Javaland)
    Object theRootOfAllEvil; // a raw instance of the superclass
    int i; // the only member that is not an Object
}

请原谅我的爪哇人,但我来自哪里都没有错;)

这一切都取决于你班级的细节。