添加更多行为而不创建新类

Bil*_*lla 11 c# oop design-patterns design-principles

这是接受采访时提出的问题.

Label一个属性Text
在一个页面中标签很简单Label,在其他页面中它可以处理任何一个或以下动作的组合
Clickable
Resizable
Draggable

如何设计应用OOP设计原理和设计模式的标签组件?

我说我会创建以下内容:

public class Label
{
  public string Text{get;set;}
}
public interface IClickable
{
 void Click();
}

public interface IDraggable
{
 void Drag();
}
public interface IResizable
{
 void Resize();
}
Run Code Online (Sandbox Code Playgroud)

因此,如果客户想要Resizable Label

public class ResizableLabel:Label,IResizable
{
  ....
}
Run Code Online (Sandbox Code Playgroud)

同样的道理ClickableLable,DraggableLabel

但是,我觉得这是不正确的方法,因为我不想添加那些具体的类.我想避免ClickableAndDraggableLabelClickableDraggableResizableLabel.

是否有任何设计模式可以在不添加这些具体类的情况下解决此问题?

Ily*_*nov 9

我会用Decorator模式.它在.net世界中广泛用于不同类型的流,例如,它允许您为字节流组合加密的,压缩的文本流包装器.类图取自维基

在此输入图像描述

您的情况示例在实现中并不是那么简单,但是使用不需要其他类来进行新的编译行为:

// Define other methods and classes here
public class Label
{
    public string Text{get;set;}

    public virtual void MouseOver(object sender, EventArgs args) { /*some logic*/ }
    public virtual void Click(object sender, EventArgs args) {  /*some logic*/ }

    //other low level events
}

public class ClikableLabel : Label
{
    private Label _label;

    public ClikableLabel(Label label)
    {
        _label = label; 
    }

    public override void Click(object sender, EventArgs args) 
    {   
        //specific logic
        _label.Click(sender, args);
    }
}

public class DraggableLabel : Label
{
    private Label _label;

    public DraggableLabel(Label label)
    {
        _label = label; 
    }

    public override void Click(object sender, EventArgs args) 
    {   
        //specific logic
        _label.Click(sender, args);
    }
}
public class ResizableLabel : Label
{
    private Label _label;

    public ResizableLabel(Label label)
    {
        _label = label; 
    }

    public override void MouseOver(object sender, EventArgs args) 
    {   
        //specific logic
        _label.MouseOver(sender, args);
    }

    public override  void Click(object sender, EventArgs args) 
    {
        //specific logic
        _label.Click(sender, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以

var clickableDragableLabel = new ClikableLabel(new DraggableLabel(new Label{Text = "write me!"}));

var makeItResizable = new ResizableLabel(clickableDragableLabel);
Run Code Online (Sandbox Code Playgroud)

  • 不要这样做.ResizableLabel不应该知道Clickable.ResizableLabel实现Click方法没有意义.装饰者模式并不意味着这样做. (2认同)

Say*_*yse 1

我只需要CanClickdrag和的布尔属性resize,所有属性都默认为 true,并根据需要(或继承)设置为 false。

构造函数如下

public Label(bool canClick = true, bool canDrag = true, bool canResize = true){}
Run Code Online (Sandbox Code Playgroud)

如果他们延长一次课程,以后很可能会进一步延长