注册观察者的最佳选择是什么?我没有找到关于这个主题的任何内容.讨论了大多数“推与拉”,但也有一些注册观察者的选项.
public static void main(String[] args)
{
Subject subject = new ConcreteSubject();
// External registration
Observer observerExternal = new ConcreteObserverExternal();
subject.registerObserver(observerExternal);
// Internal registration, option 1
Observer observerInternal1 = new ConcreteObserverInternal1(subject);
// Internal registration, option 2
ConcreteObserverInternal2 observerInternal2 = new ConcreteObserverInternal2(subject);
}
interface Observer
{
void inform();
}
class ConcreteObserverExternal implements Observer
{
@Override
public void inform()
{
// do sth.
}
}
class ConcreteObserverInternal1 implements Observer
{
public ConcreteObserverInternal1(Subject subject)
{
subject.registerObserver(this);
}
@Override
public void inform()
{
// do sth.
}
}
class ConcreteObserverInternal2
{
public ConcreteObserverInternal2(Subject subject)
{
subject.registerObserver(() -> inform());
}
private void inform()
{
// do sth.
}
}
interface Subject
{
void registerObserver(Observer obs);
void unregisterObserver(Observer obs);
}
class ConcreteSubject implements Subject
{
@Override
public void registerObserver(Observer obs)
{
// register
}
@Override
public void unregisterObserver(Observer obs)
{
// unregister
}
private void foo()
{
// ...
notifyObservers();
}
private void notifyObservers()
{
// notify observers
}
}
以下是我的代码中的三种情况:
>观察员在程序启动时注册,永远不会注册.在这种情况下,所有3个选项都是可能的.
>观察者在某处注册,并且在发生某些外部事件时需要取消注册.观察者不知道这个外部事件,显然它必须在外部注册(选项1).
>观察者在某处注册,并且在发生某些外部事件时需要取消注册.观察者知道发生了什么,因为它也是这个外部事件的观察者.在这种情况下,所有3个选项都是可能的.
在所有3个选项都可能的情况下,从OO和清洁代码的角度来看哪一个是最好的?
以下列出了我认为每个选项都有的优缺点.
1.外部登记
优点:
– 观察者的构造函数中的参数较少.
– 不需要抽象主语来促进主语和观察者之间的松散耦合.
缺点:
– 不要忘记在客户端代码中注册观察者.
– 客户代码负责注册.
中性:
– 观察者有一个额外的公共方法.
– 观察者可以通过客户端代码注册/取消注册.
2.内部注册,选项1:具体观察者实现Observer接口
优点:
– 观察员负责注册.
– 注册不能忘记,因为一个人被迫将主题传递给观察者的构造函数.
缺点:
– 观察者的构造函数中的另一个参数.
中性:
– 观察者有一个额外的公共方法.
– 观察者可以通过客户端代码注册/取消注册.
– 观察者可以注册/注销自己.
3.内部注册,选项2:具体观察者不实现Observer接口
优点:
– 观察员负责注册.
– 注册不能忘记,因为一个人被迫将主题传递给观察者的构造函数.
– 观察者没有可能被与“主体通知观察者”无关的任何内容滥用的其他公共方法.
缺点:
– 观察者的构造函数中的另一个参数.
中性:
– 观察者只能注册/注销自己.
最佳答案 鉴于您在“外部”和“内部”注册之间提出的细微差别,看起来似乎没有一个正确的答案.不过,我会试试.
我更喜欢“外部”注册其他两个,原因有两个:
>观察员对这些主题一无所知;即它们相当分离.例如,我可以将一个观察者附加到多个主题,并且没有人必须更改.
>更符合单一责任原则.观察者只关心在得到通知时需要做什么.它不关心注册/取消注册任何人.