超越开闭原则

2024-03-25

我有一个简单的程序,它根据用户提供的鼠标数据绘制几何图形。 我有一个处理鼠标跟踪的类(它获取带有鼠标移动历史记录的列表)和一个 名为 Shape 的抽象类。从这个类中,我派生了一些额外的形状,如圆形、矩形等,并且它们中的每一个都覆盖了抽象的 Draw() 函数。

一切都很好,但是当我希望用户能够切换所需的形状时,问题就来了 手动。我得到了鼠标数据,我知道我应该画什么形状。问题是如何让代码“知道”应该创建并传递哪个对象 为构造函数提供适当的参数。此时也不可能添加新的 Shape 导数,这显然是错误的。

我显然不想写出这样的代码:

List<Shape> Shapes = new List<Shape>();
// somwhere later 

if(CurrentShape == "polyline"){
    Shapes.Add(new Polyline(Points)); 
}
else if (CurrentShape == "rectangle"){
    Shapes.Add(new Rectangle(BeginPoint, EndPoint));
}
// and so on.

上面的代码显然违反了开闭原则。问题是我不知道如何克服它。主要问题是形状不同 有不同参数的构造函数,这使得它变得更加麻烦。

我很确定这是一个常见问题,但我不知道如何解决它。你有什么想法吗?


当您需要创建全部派生自单个类或实现相同接口的对象时,一种常见的方法是使用factory http://en.wikipedia.org/wiki/Factory_method_pattern。然而,就您而言,一个简单的工厂可能还不够,因为工厂本身需要可扩展。

一种实现方法如下:

interface IShapeMaker {
    IShape Make(IList<Point> points);
}
class RectMaker : IShapeMaker {
    public Make(IList<Point> points) {
        // Check if the points are good to make a rectangle
        ...
        if (pointsAreGoodForRectangle) {
            return new Rectangle(...);
        }
        return null; // Cannot make a rectangle
    }
}
class PolylineMaker : IShapeMaker {
    public Make(IList<Point> points) {
        // Check if the points are good to make a polyline
        ...
        if (pointsAreGoodForPolyline) {
            return new Polyline(...);
        }
        return null; // Cannot make a polyline
    }
}

用这些Maker手头有课程,您可以制作制造商注册表(一个简单的List<IShapeMaker>)通过制作者将点传递给他们,并在返回非空形状时停止。

该系统仍然是可扩展的,因为您可以添加一对NewShape and NewShapeMaker,并将它们“插入”现有框架:一次NewShapeMaker进入注册表后,系统的其余部分立即准备好识别和使用您的NewShape.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

超越开闭原则 的相关文章

随机推荐