如何在解耦对象之间强制执行约束?

时间:2010-11-08 18:36:25

标签: c# events decoupling intercept

5 个答案:

答案 0 :(得分:1)

你知道宇宙飞船必须有尺寸;将Size放在基类中,并在那里的访问器中实现验证检查。

我知道这似乎过分关注您的具体实施,但这里的重点是您的期望并不像您预期​​的那样脱钩;如果你对派生类中某些东西的基类有一个期望,你的基类正在对派生类提出一个基本的期望,提供一个实现;也可以将该期望直接迁移到基类,在那里您可以更好地管理约束。

答案 1 :(得分:1)

您可以执行类似C ++ STL traits类的操作 - 实现一个通用SpaceBase<Ship, Traits>,它有两个参数化Type s - 一个定义SpaceShip成员,另一个约束{ {1}}及其SpaceBase使用SpaceShip类来封装基础的特征,例如它可以包含的船舶的限制。

答案 2 :(得分:1)

INotifyPropertyChanging界面是为数据绑定而设计的,这解释了为什么它没有你正在寻找的能力。我可能会尝试这样的事情:

interface ISpacebaseInterceptor<T>
{ 
    bool RequestChange(T newValue); 
    void NotifyChange(T newValue); 
} 

答案 3 :(得分:1)

答案 4 :(得分:1)

您希望对操作应用约束,但将其应用于数据。

首先,为什么允许更改Starport.MaximumShipSize?当我们“调整大小”时,Starport不应该所有的船都起飞吗?

这些问题是为了更好地理解需要做什么(并且没有“对与错”的答案,有“我的和你的”)。

从其他角度看问题:

public class Starport
{
    public string Name { get; protected set; }
    public double MaximumShipSize { get; protected set; }

    public AircarfDispatcher GetDispatcherOnDuty() {
        return new AircarfDispatcher(this); // It can be decoupled further, just example
    }
}

public class Spaceship
{
    public double Size { get; private set; };
    public Starport Home {get; protected set;};
}

public class AircarfDispatcher
{
    Startport readonly airBase;
    public AircarfDispatcher(Starport airBase) { this.airBase = airBase; }

    public bool CanLand(Spaceship ship) {
        if (ship.Size > airBase.MaximumShipSize)
            return false;
        return true;
    }

    public bool CanTakeOff(Spaceship ship) {
        return true;
    }

    public bool Land(Spaceship ship) {
        var canLand = CanLand(ship);
        if (!canLand)
            throw new ShipLandingException(airBase, this, ship, "Not allowed to land");
        // Do something with the capacity of Starport
    }

}


// Try to land my ship to the first available port
var ports = GetPorts();
var onDuty = ports.Select(p => p.GetDispatcherOnDuty())
    .Where(d => d.CanLand(myShip)).First();
onDuty.Land(myShip);

// try to resize! But NO we cannot do that (setter is protected)
// because it is not the responsibility of the Port, but a building company :)
ports.First().MaximumShipSize = ports.First().MaximumShipSize / 2.0