OOD和主题 - 对象混淆

xof*_*ofz 3 c# oop

假设我有一个门的定义:

class Door
{
    public void Lock()
    {
        // lock the door
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎对我有意义,至少在一段时间内.但现在,我不太确定.如果我有一个想要锁门的Person对象,他会调用aDoor.Lock().但在现实生活中,我们不会通过告诉门锁自己锁门.

似乎更准确的情况模型是能够直接修改门的状态的人,只要他有足够的力量来锁门.例如,aCat不能设置aDoor.IsLocked = true.如果它们支持参数,我可以看到如何使用属性执行此操作:

class Person
{
    public void LockDoor(Door door)
    {
        door.IsLocked(this) = true;
    }
}

class Door
{
    bool isLocked;

    public bool IsLocked(Person person)
    {
        set
        {
            if(person != null) // ensure there is a real person trying to lock the door
            {
                this.isLocked = value;
            }
        }
    }
}

static void Main()
{
    Person personFromThinAir = new Person();
    Door doorFromThinAir = new Door();
    personFromThinAir.LockDoor(doorFromThinAir);
}
Run Code Online (Sandbox Code Playgroud)

相反,我们能做的是:

class Person
{
    public void LockDoor(Door door)
    {
        door.SetLocked(this, true);
    }
}

class Door
{
    bool isLocked;

    public void SetLocked(Person person, bool locked)
    {
        if(person != null)
        {
            this.isLocked = locked;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

显然这两个类是强耦合的,两者都可能在实际代码中提取接口,但这不是我所得到的.我的问题是,这是一种更好的方法来模拟两个对象之间的关系吗?还有比这更好的方法吗?我想的越多,aDoor.Lock()的感觉就越少; 它似乎违反了面向对象的设计.

ape*_*ins 9

虽然该人"锁定"门,但实际上该人正在切换(或擦拭)门的元件(锁定手柄)并且该操纵导致锁锁定门.你可以想到这一点,虽然这个人正在移动锁舌,但是锁舌是锁门的 - 而不是人.因此,一个更好的表示可能是门有一个锁,并且该人调用lock.lock(),然后设置锁被关闭(锁定).

这里的基本前提是,虽然人正在操纵锁,但这是外部的(函数调用).锁的内部更改(函数内部的代码)实际上是导致门锁定的原因.这个人每次都没有脱下手柄并操纵内部来锁门 - 他们只是在外面切换状态并期望机器内部处理它.


Ken*_*ran 6

OOP并不是关于在"现实世界"中如何工作的建模.它更多的是管理复杂性.考虑到这一点,门完全锁定是完全可以接受的.即使在现实世界中,除了转动旋钮或钥匙之外,锁门的人不需要知道锁的工作原理.

隐藏抽象背后的复杂想法的细节是OOP如此有用的原因.您使用的抽象与问题域不同.在你给出的例子中,除了如何操作之外,人们不需要知道关于门的任何信息:

class Door
{
    public bool Open(){}
    public bool Close(){}
    public void Lock(){}
    public void Unlock(){}
}
Run Code Online (Sandbox Code Playgroud)