2009-07-27 122 views
3

假设我有一个门一个定义:OOD和主客混乱

class Door 
{ 
    public void Lock() 
    { 
     // lock the door 
    } 
} 

这似乎是有意义的我,至少一段时间。但现在,我不太确定。如果我有一个想要锁门的Person对象,他会调用一个Door.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); 
} 

相反,我们所能做的就是:

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; 
     } 
    } 
} 

显然,这两个类是强耦合,并且都可能会有在实际代码中提取的接口,但这不是我所掌握的。我的问题是,这是模拟两个对象之间关系的更好方法吗?有没有比这更好的方法?我对它的考虑越多,我可以做出的Do.O.Lock()的感觉就越少;它似乎违反了面向对象的设计。

回答

9

虽然人“锁定”的大门,在现实中的人被触发(或frobbing)在门的一个元件上(锁手柄),并且该操作导致锁将门锁定。你可以想到这个地方,虽然这个人正在移动死角,但是死锁是锁门的东西 - 而不是人。所以一个更好的表示可能是一个门有一个锁,而这个人调用lock.lock(),然后设置锁被关闭(锁定)。

这里的基本前提是,虽然人在操纵锁,那是外部的(函数调用)。锁的内部变化(函数内部的代码)实际上是导致门锁定的原因。人不会每次都脱下手柄并操纵内部锁门 - 他们只是简单地在外面打开一个状态,期待内部机器处理它。

+0

好说 - 打字比我快! – 2009-07-27 16:27:30

6

面向对象并不是真正关于如何在“现实世界”中工作的建模。其更多关于管理复杂性。考虑到这一点,门自锁是完全可以接受的。即使在现实世界中,除了转动旋钮或钥匙之外,锁定门的人不需要知道锁的工作方式。

隐藏在抽象背后的复杂想法的细节是什么使OOP如此有用。您使用的抽象与问题域不同。在这个例子中你给了人不应该需要了解的门什么比如何操作其他:

class Door 
{ 
    public bool Open(){} 
    public bool Close(){} 
    public void Lock(){} 
    public void Unlock(){} 
} 
0

这里最让我感兴趣的设计问题是如何处理锁柜和锁定装置之间的耦合,因为锁定/解锁需要满足一定的要求。我看着这个问题,想象一个游戏,玩家有时可能是一个人,但其他时间是一只猫(根据给出的例子),也许is_human是锁定/解锁的唯一要求。但是,您也可能希望有门需要匹配键才能进入玩家的位置,以便锁定/解锁。如果是这样,你必须添加到标准。也许有些门只能从一侧锁定,而不能从另一侧锁定,所以玩家的位置必须添加到标准中。你可以进一步增加一些玩家可能拥有的开锁技能(无疑是猫鼬窃贼),让他们有机会解锁(但不锁)门,即使他们没有钥匙。等等

人们可以像想象中的对象之间的对话:

Player: "I am trying to unlock you." 
Lock: "Do you meet requirement A?" 
Player: "Yes" 
Lock: "Do you meet requirement B?" // Only some doors would ask this. 
Player: "Yes" 
Lock: "OK, you succeed. I am unlocked!" 

但是,你可能不希望公开揭露所涉及的领域或弄乱由不需要的对象看到的播放器界面了解锁定/解锁要求。

我不是C#程序员,从我做Java开始就已经有一段时间了,但我认为Java中的一种方法可能也适用于C#,它将让Player对象通过一个lock_unlock_credentials内部类的实例作为门对象的方法的参数(或者已经建议的锁对象).对象将具有回调方法,由于其作为玩家的内部类,可以访问玩家的相关字段对象,但这些字段否则不会暴露在玩家之外。 Lockable对象然后可以使用这些回调方法来检查它所关心的需求是否被满足。您无法避免由需求产生的耦合,但这种方式保持了Player和Lockable对象之间交互的内部细节。

不知道是否相同的内部类的方法适用于C#,但提出这是一些思考。