我在这个例子中是否违反了 LSP 原则?
Did I violate the LSP principle in this example?
我有实现 2 种门的代码。
一扇门有锁,另一扇没有。
Door 界面很简单:
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
接收锁并调用它的解锁函数来解锁锁。
是否违反里氏替换原则?
如果是,什么是好的选择?
回答这个问题有点困难,因为您的 Door
界面似乎不完整,因为不清楚 open()
和 close()
应该做什么。让我们通过添加一个 isOpen()
方法来清除它,并定义一旦 open()
被调用,对 isOpen()
的后续调用应该 return true
(我'为了简洁起见,我故意忽略了如果您尝试打开并且已经打开的门会发生什么的问题。
在这种情况下,你肯定违反了 LSP 原则 - 如果你试图打开一扇锁着的门,你会失败,而且门会保持关闭状态。
解决此问题的一种方法是向 open()
和 close()
方法添加一个 return 值,以便它们可以报告操作是否成功:
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
}
否,您(可能)没有违反 LSP。
更长的答案:当然取决于接口 Door
中 open()
方法的 "definition"。如果您将方法定义为“尝试在可能的情况下打开门”,那么您就没有问题了。
可能有人认为应该调用 open()
方法 tryOpen()
以向调用者阐明您的意图,即调用后门可能不会打开。
如果您将 open()
方法定义为 总是 打开门,那么您当然违反了 LockedDoor
中的合同(和 LSP) .
另一个问题是,界面中缺少一些东西。就目前而言,open/closed 状态对任何可用方法 open()
/close()
没有 效果 。我假设您在 Door
中有一些其他方法与门的状态相关,例如 walkThrough()
或类似的方法。
我有实现 2 种门的代码。 一扇门有锁,另一扇没有。
Door 界面很简单:
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
接收锁并调用它的解锁函数来解锁锁。
是否违反里氏替换原则?
如果是,什么是好的选择?
回答这个问题有点困难,因为您的 Door
界面似乎不完整,因为不清楚 open()
和 close()
应该做什么。让我们通过添加一个 isOpen()
方法来清除它,并定义一旦 open()
被调用,对 isOpen()
的后续调用应该 return true
(我'为了简洁起见,我故意忽略了如果您尝试打开并且已经打开的门会发生什么的问题。
在这种情况下,你肯定违反了 LSP 原则 - 如果你试图打开一扇锁着的门,你会失败,而且门会保持关闭状态。
解决此问题的一种方法是向 open()
和 close()
方法添加一个 return 值,以便它们可以报告操作是否成功:
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
}
否,您(可能)没有违反 LSP。
更长的答案:当然取决于接口 Door
中 open()
方法的 "definition"。如果您将方法定义为“尝试在可能的情况下打开门”,那么您就没有问题了。
可能有人认为应该调用 open()
方法 tryOpen()
以向调用者阐明您的意图,即调用后门可能不会打开。
如果您将 open()
方法定义为 总是 打开门,那么您当然违反了 LockedDoor
中的合同(和 LSP) .
另一个问题是,界面中缺少一些东西。就目前而言,open/closed 状态对任何可用方法 open()
/close()
没有 效果 。我假设您在 Door
中有一些其他方法与门的状态相关,例如 walkThrough()
或类似的方法。