面向对象的设计问题,Liskov替代原理 [英] Object Oriented Design Problem, Liskov Substitution Principle

查看:87
本文介绍了面向对象的设计问题,Liskov替代原理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计OO框架,并且面临以下问题.

I'm making the design of a OO framework and I'm facing the following problem.

假设我们在框架中有一个 Shape 界面,用户可以自由实现和扩展(添加新功能) Shape 界面以创建自己的图形,例如 Square Circle .为了使这些新对象可用,用户必须将它们注册到 ShapeFactory 中,并指定形状(字符串)和对象的名称.

Let's say that in the framework I have a Shape interface and the users are free to implement and extends (adding new functions) the Shape interface to create their own figures, e.g. Square and Circle. To make these new objects available the users have to register them into a ShapeFactory specifying the name of the shape (string) and the object.

此外,该框架提供了一个名为 ShapeWorker 的接口,该接口定义了以下功能:

Furthermore, the framework provides an interface called ShapeWorker which defines the following function:

class ShapeWorker
{
public:
  void processShape( Shape& shape ) = 0;
};

用户可以自由实现 ShapeWorker 界面来制作特定的形状工作器,例如 SquareWorker CircleWorker .为了使这些新对象可用,用户必须将它们注册到 WorkerFactory 中,并指定形状(字符串)和对象的名称.

The users are free to implement the ShapeWorker interface to make specific shape worker, e.g. SquareWorker and CircleWorker. To make these new objects available the users have to register them into a WorkerFactory, specifying the name of shape (string) and the object.

在某一点上,给定表示形状名称的字符串的框架会使用 ShapeFactory 创建一个新的 Shape ,此后(在其他地方代码),使用具有相同形状名称的 WorkerFactory 创建一个新的 ShapeWorker .然后调用 processShape ,以提供之前创建的 Shape 实例.

At a certain point, the framework, given a string representing the shape's name, creates a new Shape, by using the ShapeFactory, and afterwards (somewhere else in the code) creates a new ShapeWorker, by using the WorkerFactory with the same shape's name. The processShape is then called providing the Shape instance created before.

[ ... ]
Shape* myShape = shapeFactory.create( shapeName );
[ ... ]
ShapeWorker* myWorker = workerFactory.create( shapeName );
myWorker->processShape( *myShape );
[ ... ]

重点是,这样做,我迫使实施例如 SquareWorker 的用户将 Shape 转换为 Square 进入 processShape 函数,以便访问完整的 Square 界面:

The point is that, doing so, I force the user implementing, for example, the SquareWorker to make a down-cast from Shape to Square into the processShape function so to access to the full Square's interface:

class SquareWorker
{
public:
  void processShape( Shape& shape )
  {
     Square& square = dynamic_cast< Square& >( shape );
     // using Square interface
  }
};

这违反了Liskov替代原则.

This is against the Liskov substitution principle.

现在,这种方法错误吗?有什么更好的解决方案?请注意,我不想将processShape实现为 Shape 的成员函数.

Now, is this approach wrong? What would it be the better solution? Note that I don't want to implement the processShape as Shape's member function.

我希望说明已经足够清楚了.

I hope the description has been clear enough.

预先感谢您的帮助.

Simo

推荐答案

除非您的形状具有必须由工作人员使用的公共界面,否则这种方法对我而言似乎是完全正确的.形状工作者或多或少地专注于特定形状,因此具有有关其处理的类的知识.最好对所有形状使用一个通用的界面,但是您无法将所需的所有东西都放进去,最终会变得很杂乱.垂头丧气是解决这个问题的正确方法.

Unless your shapes have a common interface that must be used by the workers, this approach seems fully correct to me. A shape worker is more or less specialized on a specific shape, thus has knowledge about the class it handles. It would be nicer to do that using a common interface for all shapes but you cannot put everything you would need into it, it would end up fully cluttered. Downcasting is a correct mean to solve this.

使用模板可以为您提供帮助:您可以为所有工作人员创建基类

The use of templates could help you out: you could create a base class for all workers

template <class T> 
class BaseShapeWorker : ShapeWorker
{
public:
  void processShape( Shape& shape )
  {
     T& specificShape = dynamic_cast< T& >( shape );
     processShape( specificShape )
  }
protected:
  virtual void processShape( T& shape ) = 0;
};

这可能不需要实现者了解此失败消息,也不需要通过提供一些经常重用的功能来简化实现.

This would not need the implementers to know about this downcast and ease the implementation by maybe also providing some often reused functionality.

这篇关于面向对象的设计问题,Liskov替代原理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆