开发者

Interface as a capability or Interface as a Type

Suppose I have such requirement:

The objects in the system all derive from a base class named IObject, and it may have objects with color, objects with transformations, and both.

Now there are 2 approach to design the class hierarchy.

The first one is:

just let concrete class derived from IObject, and also select "capability" interfaces as its base class to indicate it support such behavior, like interface: IHasColor,

IHasTransformation

The second one is:

Organize the base classes, and let concrete classes derived from one of 开发者_StackOverflow中文版 them: IObject, IColorObject, ITransfromationObject , IColorAndTransformationObject

I prefer the first one (Does it have a formal name? ) as it is more flexible, and as you can see the second one may have class combination explosion problem when there are many attributes like color, transformation...

I would like to know your ideas and suggestions.

Thanks.


Classes abstract the real concept of types of objects.

Interfaces abstract the real concept of behaviors or abilities for an object.

So the questions becomes, is the "color" a property of the object or is it a capability of the object?

When you design a hierarchy you are constraining the world into a narrower space. If you take the color as a property of the object then you will have two kind of objects, the ones that have colors and the ones that do not. Does that fit your "world"?

If you model it as a capability (Interface) then you'll have objects that are able to provide, lets say cast, colors to the world.

For the transformation the same logic applies. You can either split the world into two kind of objects, the ones who can transform and the ones who can not, or you can view it as a capability, an object may have the ability to transform itself into another thing.

For me, from that point of view, what would make sense would be:

  • Color is a property of the object. In fact every object should have a color, even if its transparent, even if is reflection, even if its "none" (good luck figuring out what an object with color = none means in the real world, still it might make sense in your program logic).
  • Transformation is a capability, that is, an interface, something the object is capable of doing, among other things the object may or may not be able of doing.


I'm working on classes hierarchy in my project and basically I have similar situation like you described in your question.

Let's say I have base type Object which is absolute root of all other classes in my toolkit. So naturally everything derives from it directly or through it's subclasses. There is a common functionality that every Object-derived class has to provide but in some leaf classes effects are little different than in others. For example every object have size and position which can be changed with properties or methods like Position = new Point(10, 10), Width = 15, etc. But there are classes that should ignore setting of a property or modify it according to self inner state. Think about control docked to left side of parent window. You can set Height property all you like but it will be generally ignored because this property really depend on Height of parent container control (or it's ClientArea height or sth like that).

So having Object abstract class implementing basic common functionality is ok until you reach a point of where you need "customize" behavior. If Object provides protected virtual SetHeight method that is called in setter of Height property you can override it in you DockedControl class and allow change of height only if docking is None, in other cases you limit it or ignore completely.

So we are happy but now we have requirement for object that react on mouse events like Click or Hover. So we derive MouseAwareObject from abstract Object class and implement events and stuff.

And now client want dockable, mouse aware objects. So we derive from DockableObject and... hmm, what now? If we can do multiple inheritance we can do it but we hit diamond problem with ambiguity of duplicated interface and we need to deal with it. We can have two memeber of Dockable and MouseAware types in new class and proxy external calls to them to provide functionality.

And last thing that comes to mind is to make IDockable and IMouseAware interfaces and let them define functionality and add them freely only to objects that need to deliver concrete behaviors/implementations.

I think I will split my base class into parts and leave my Object with very limited "core" set of properties and methods and rest of functionality that is in fact optional to Objects as a type but needed in concrete cases move to interfaces like IResizable, IDockable, IMakeAWorldABetterPlaceAble, etc. With this solution it is possible to "attach" behaviors to Object-derived classes without need for draggin virtual or pure virtual (abstract) methods from root base class all the way down to leaf class.

There is of course inconvenience of implementing interfaces in all affected classes but you can always implement some "adapters" and just forward calls to them. That way you don't have duplicated implementation (to some extend of course) and have decoupling between realization of task (Resize can mean different things for different classes) and expectation of client code.

Probably this is not ideal answer for your question but maybe it will hint you to your own solution.


I think you jump directly into interfaces, skipping classes. Is it required for you app. to have a "IObject" interface ? Maybe a "CObject" root class for your class hierarchy, may help you.

It think the winner is No. 1 solution, you may have a "MyObject", whether is an implementation of an interface, or direct class. Later you can add additional classes or interfaces in your class hierarchy, as you need.

After seeing several applications (some mine, some others), I think there should be a "My Custom Application Class Hierarchy Root Object" or "My Custom Application Class Hierarchy Root Interface" Design Pattern.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜