【问题标题】:Modifiy deeply nested dependencies修改深度嵌套的依赖
【发布时间】:2015-06-22 13:25:36
【问题描述】:

访问/修改深度嵌套对象的正确方法是什么?

看下面的例子。

public class DrawBoard
{
    MouseTracker mouseTracker_;
    DrawTool* drawTool_;

    void init()
    {
        mouseTracker_ = new MouseTracker(area);
        mouseTracker_.setTool(new PenTool());
    }

    void OnMouseEvent(MouseEvent e)
    {
        mouseTracker_->handleMouseEvent(e);
    }

    //UI Button setting the tool
    void OnPenButtonClick()
    {
        mouseTracker_.SetTool(new PenTool());
    }

    void OnLineButtonClick()
    {
        mouseTracker_.SetTool(new LineTool());
    }

    void OnCircleButtonClick()
    {
        mouseTracker_.SetTool(new CircleTool());
    }

    //UI slide bar changing the color
    void OnColorSlideBarChange(int color)
    {
        //What should I do here?
        //Chained getters : mouseTracker.getDrawTool().setColor(color);
        //Delegate Method: mouseTracker.setColor(color);
        //Shared Object: Store the current tool in "drawTool_" -    drawTool_ = new PenTool(); 
        //                                                          mouseTracker_.SetTool(drawTool_);
        //and just call drawTool_.setColor(color) on color change
    }
}

public class MouseTracker;
{
    DrawTool* tool_;

    void handleMouseEvent(MouseEvent e)
    {
        Shape s = tool->process(e)
        s.Draw();
    }

    void SetTool(DrawTool tool)
    {
        tool_ = tool;
    }
}

public class DrawTool
{
    int color_;

    Shape* process(MouseEvent e)
    {
        /** process e **/
        Shape s = new Pen\Line\Circle(color_);
        return s;
    }

    void SetColor(int color)
    {
        color_ = color;
    }

} PenTool, LineTool, CircleTool;

public class Shape
{
    void Draw() {  Implementation };

} Pen, Line, Circle;

DrawBoard 是一个 UI 类。

MouseTracker 是一个用于处理事件并采取相应措施的类。

DrawTool 是用于创建Shapes 的类。 PenToolLineToolCircleTool 是它的子类。

Shape 是用于绘制的类。 PenLineCircle 是它的子类。

现在从 DrawBoard 开始,我正在尝试根据 UI 事件(在本例中为 OnColorSlideBarChange)更改 drawTool 的颜色。我只能看到 3 种方法。

链式吸气剂

mouseTracker.getDrawTool().setColor(color); 但上面的例子是一个简化的例子。如果两者之间有更多的依赖关系。它可能会很快成长为

mouseTracker.getA().getB().getC().getDrawTool().setColor(color); 我必须为每个类编写一个 getter 方法。

委托方法

mouseTracker.setColor(color);

与上面类似,只是我在一个委托方法中隐藏了细节。

共享对象

将当前工具存储在DrawBoard 类中的“drawTool_”中,并在每次工具更改时更新它

drawTool_ = new PenTool(); 
mouseTracker_.SetTool(drawTool_);

改变颜色只是

drawTool_.setColor(color)

但我这样做似乎打破了封装。

有没有更好的方法来处理这种情况?

【问题讨论】:

    标签: design-patterns dependency-injection dependencies


    【解决方案1】:

    您使用共享对象的最后一个示例并没有真正破坏封装,并且与我建议的通过结合依赖倒置和关注点分离的概念来实现它的方式接近。

    我唯一要问的是为什么鼠标跟踪器关心当前正在使用的工具。根据它的名字,它应该只关心跟踪鼠标和确定位置数据;可能包装一些方便的方法来确定状态,比如IsDragging 属性。然后控制器类(在这种情况下为绘图板)应获取该数据(和/或响应您的跟踪器发布的鼠标状态更改事件)并使用它与工具产生的结果一起更新您的绘图空间.

    话虽如此,您最初问题的答案是将这种深度访问视为一种编码气味,并确保您无法使用 SOLID 原则和常见模式更改设计。如果您的设计确实需要深度访问,请根据具体情况确定消费者是否需要对完整对象或单个属性进行深度访问。如果是前者,则公开子对象。如果是后者,请创建一个获得所需内容的包装器属性。在每个级别做出决定,然后在每个级别访问最深的可用属性。基本上你只需要在不想暴露所有东西和不想总是在每个对象上都有十亿个属性来访问更深层次的对象之间找到平衡。

    【讨论】:

    • 我也在考虑“扁平化”结构。 MouseTracker 将触发一个事件,然后该工具将响应此事件并进行绘制。但我认为它可能会在控制器类中公开一些实现细节。我想我对这个封装的事情“想多了”。现在我会使用共享对象方法:)
    猜你喜欢
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多