我有这个代码实现了两种类型的门。 一扇门包含锁,另一扇门没有。
门界面毫无疑问:
public interface Door {
void open();
void close();
}
然后我有实施: LockedDoor 和 RegularDoor
public class LockedDoor implements Door {
private Lock lock;
private boolean isOpen;
@Override
public void open() {
if(!lock.isLocked()) {
this.isOpen = true;
}
}
@Override
public void close() {
this.isOpen = false;
}
}
public class RegularDoor implements Door {
private boolean isOpen;
@Override
public void open() {
isOpen = true;
}
@Override
public void close() {
isOpen = false;
}
}
如您所见,LockedDoor
的打开功能只有在解锁时才会打开门。
您可以通过从LockedDoor
接收锁定并调用它的解锁功能来解锁。
是否违反Liskov替代原则?
如果是的话,什么是一个好的选择?
答案 0 :(得分:2)
有点难以回答这个问题,因为Door
的界面似乎不完整,因为它不清楚open()
和close()
是什么意思去做。让我们通过添加isOpen()
方法清除它,并定义一旦调用open()
,后续调用isOpen()
应该返回true
(和我&# 39;如果你试图打开并且已经打开门,为了简洁起见,故意忽略了会发生什么的问题。
在这种情况下,你肯定违反了LSP的原则 - 如果你试图打开一扇锁着的门,你就会失败,而且门会保持关闭状态。
解决此问题的一种方法是向open()
和close()
方法添加返回值,以便他们可以报告操作是否成功:
public interface Door {
/**
* Checks if the door is open.
* @return {@code true} if the door is open, {@code false} if not.
boolean isOpen();
/**
* Attempt to open the door.
* @return {@code true} if the door was successfully opened,
* {@code false} if not.
* In other words, if a call to {@code open} returns {@code true}, a
* subsequent call to {@link #isOpen} will return {@code true}.
*/
boolean open();
/**
* Attempt to close the door.
* @return {@code true} if the door was successfully closed,
* {@code false} if not.
* In other words, if a call to {@code close} returns {@code true}, a
* subsequent call to {@link #isOpen} will return {@code false}.
*/
void close();
}
public class RegularDoor implements Door {
private boolean isOpen;
@Override
public boolean isOpen() {
return isOpen;
}
@Override
public boolean open() {
return isOpen = true;
}
@Override
public boolean close() {
return isOpen = false;
}
}
public class LockedDoor implements Door {
private Lock lock;
private boolean isOpen;
@Override
public boolean isOpen() {
return isOpen;
}
@Override
public boolean open() {
if (!lock.isLocked()) {
return isOpen = true;
}
return false;
}
@Override
public boolean close() {
return isOpen = false;
}
// Not shown here - methods to lock and unlock the door
}
答案 1 :(得分:1)
否,您(可能)没有违反LSP。
更长的答案:当然取决于界面open()
中Door
方法的“定义”。如果您将方法定义为“尝试打开门,如果可能”,那么您就是明确的。
可能有人认为应该调用open()
方法tryOpen()
来澄清你打电话给呼叫后门可能没有打开的意图。
但是,如果您将<{1}}方法定义为总是打开门,那么您当然违反了open()
中的合同(和LSP)。
另一个问题是,界面中缺少某些东西。就目前而言,打开/关闭状态对任何可用方法LockedDoor
/ open()
都没有效果。我假设你在close()
中有一些与门的状态相关的其他方法,例如Door
或类似的东西。