Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在这个例子中,我是否违反了LSP原则?_Java_Oop_Design Patterns_Solid Principles_Liskov Substitution Principle - Fatal编程技术网

Java 在这个例子中,我是否违反了LSP原则?

Java 在这个例子中,我是否违反了LSP原则?,java,oop,design-patterns,solid-principles,liskov-substitution-principle,Java,Oop,Design Patterns,Solid Principles,Liskov Substitution Principle,我的代码实现了两种类型的门。 一扇门有锁,另一扇门没有 门界面非常简单: public interface Door { void open(); void close(); } 然后是实现:LockedDoor和RegularDoor public class LockedDoor implements Door { private Lock lock; private boolean isOpen; @Override public voi

我的代码实现了两种类型的门。 一扇门有锁,另一扇门没有

界面非常简单:

public interface Door {
    void open();
    void close();
}
然后是实现:LockedDoorRegularDoor

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替代原则?

如果是,那么什么是一个好的选择?

回答这个问题有点困难,因为您的
门的接口似乎不完整,因为不清楚
打开()
关闭()
应该做什么。让我们添加一个
isOpen()
方法,并定义一旦调用
open()
,对
isOpen()
的后续调用应该返回
true
(为了简洁起见,我故意忽略了如果您试图打开并且已经打开门会发生什么的问题)

在这种情况下,你肯定违反了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
}

,您(可能)没有违反LSP

更长的回答:当然取决于您对界面
中的
open()
方法的“定义”。如果您将该方法定义为“如果可能,尝试打开门”,则您处于清除状态

有人可能会争辩说,应该调用
open()
方法
tryOpen()
,以向调用方阐明您的意图,即调用后门可能不会打开

但是,如果您定义了
open()
方法来始终打开门,那么您当然违反了
LockedDoor
中的合同(和LSP)


另一个问题是,接口中缺少一些东西。目前,打开/关闭状态对任何可用方法都没有影响
open()
/
close()
。我假设您在
门中有一些与门的状态相关的其他方法,例如
漫游()
或类似的方法。

您的问题在这里更合适:为什么您认为需要两个不同的类?一门课不够吗?你只需要检查
isOpen
状态,如果门被锁或没有锁:)@KarelG在引用其他站点时,我认为最好是在无法打开时使open()抛出异常。通过使用命令方法的返回值,您可以中断CQS,尽管区分成功和失败的open()执行仍然有好处。异常清楚地表明,要么命令成功,要么我们应该转到不同的执行流。