我对观察者模式有疑问。它说 Observer 和 Subject 都应该是接口。我明白为什么观察者是接口,但为什么让主题成为抽象类不是更好?难道你不能至少实现删除/注册吗?
5 回答
设计模式旨在适应应用程序的特定需求;他们没有规定一成不变的规则。特别是某个东西是抽象类还是接口由您决定,考虑到该决定对应用程序其余部分的所有影响。
也就是说,通常出于几个原因,建议使用接口而不是抽象类。例如,抽象类要求您使用继承,而在许多语言中,您不能从多个类继承。如果这对您的用例来说不是问题,请继续使用抽象类,如果您觉得它们更方便的话。
为什么不只拥有一个实现 Subject 的抽象类呢?使用界面只会为您提供更大的灵活性。从抽象类开始并没有真正给你带来任何好处。如果每件事都发生了很大的变化(比如跨越进程边界),那么您的 Observable 将被抽象实现所困。
在使用接口一词的设计模式中,它意味着向客户端组件公开的抽象 API,这些组件将具有不同的具体实现。
当设计模式接口映射到 Java 世界时,它可以是 Java 接口或 Java 抽象类,而设计模式具体类映射到 Java 常规类(非抽象)。
但是,在做出决定时,您确实需要了解 Java 接口和抽象类之间的区别以及它们的用途以及优缺点。
请参阅:接口与抽象类
为什么将主题设置为抽象类不是更好
避免将设计与特定的具体实现联系起来。请记住,目的是创建一个模式,让您可以根据需要灵活地交换具体主题,并且不会让观察者与任何原始实现相关联。
您不希望观察者引用 a FirstConcreteSubject
,而是引用一个 interface ISubject
,可以快速将其更改为由 a 实现,SecondConcreteSubject
而无需修改观察者。
也就是说,拥有一个BaseSubject
抽象类来存储一些本来会被 and 复制的代码FirstConcreteSubject
并没有错(IMHP) SecondConcreteSubject
。
Java 接口描述类型(如设计模式一书所定义)。Java 接口的限制因素是您不能声明观察者列表所需的实例变量。
这就是抽象类的用武之地。您可以像这样声明一个实例变量:
import java.util.List;
public abstract class Subject {
List<Observer> observers; // this would not be allowed in an interface
public void attachObserver(ObjectObserver objectObserver) {
// implementation
};
public void detachObserver(ObjectObserver objectObserver) {
// implementation
};
public abstract void notifyObservers();
}
但是,接口更好,因为它们更擅长强制封装。您可以通过在接口中声明三个方法来添加另一层抽象,接口中依次声明这些方法/“类型”。然后抽象类可以实现这些方法。