class 内可能存在空接口对象的最佳实践

Best practice with a possibility of a null interface object within class

我创建了一个代表组件的 class。这个组件有width,height,x-Coordinate,y-Coordinate等。当我操作width,height,x,y时,我想把逻辑保持在class之内。但是 Component Class 中有一个接口对象具有相似的值。此接口可用于与不同类型的 CAD 软件通信。不过 Shape 接口可以为 null。

所以我的问题是最好的方法是什么?在下面的示例中,当我更改 "Y" 时,是否应该检查形状界面中的空值?或者也许组件 Class 有事件处理程序,Shape 接口应该向它们注册。那么什么是设计这种方法的最佳实践,什么能提供最佳性能?

点赞!

public class Component
{
    private double _y;

    public IShape Shape { get; set; }
    public string Name { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public double X { get; set; }

    public double Y
    {
        get => _y;

        set
        {
            _y = value;
            if (Shape != null) Shape.Y = value;
        }
    }

    public void Update_Shape()
    {
        //used to update the Shape Interface after it is assigned
    }

}

public interface IShape
{
    string Name { get; set; }
    double Width { get; set; }
    double Height { get; set; }
    double X { get; set; }
    double Y { get; set; }
}

更新:为了提供更多细节,我的界面将能够与 Microsoft Visio 和 AutoCad 对话。它们仅用作数据的可视化表示,无法控制形状的数量或位置。所以在我的应用程序中,用户可以在应用程序内移动或更改 width/height。如果他们当时打开了 Visio,我希望它也能更新 Visio 形状。如果它没有打开,那么没关系(它最终会在稍后更新)。 AutoCad 也是如此。

这种情况下的最佳做法取决于您的设计目标。

如果您想自动更新 IShape 并且性能很关键,那么手动写出您的 setter 并进行空检查将同时满足您的需求。拥有 IShape 订阅的事件导致您必须调用比检查 null 更昂贵的事件。这有利于保持 class 内的混乱,因为您只需要分配 myComponent.X = 20;

举办活动有好处。如果您查找观察者模式,您会发现很多关于此的好读物。如果您有多个 IShape 订阅您的 Component,请同时从 Visio 和 AutoCad 说这将是可行的方法。

现在就性能而言,如果您每秒更新的组件少于几千个并且您想要更简洁的代码,我会在您想要同步值时调用 Update_Shape()。如果您同时分配多个值,您可以将它们包装在一个操作中,该操作将在完成后自动同步这些值。

var c = new Component();
c.Shape = new Shape();

c.UpdateShapes(s => {
    s.Height = 100;
    s.Width = 100;
    s.X = 5;
});
public class Component
{
    public IShape Shape { get; set; }
    public string Name { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public double X { get; set; }
    public double Y { get; set; }

    public void UpdateShapes(Action<Component> update)
    {
        update(this);
        SyncronizeShapes();
    }

    public void SyncronizeShapes()
    {
        if (Shape != null)
        {
            Shape.Name = Name;
            Shape.Width = Width;
            Shape.Height = Height;
            Shape.X = X;
            Shape.Y = Y;
        }
    }
}