Rav*_*avi 191 java design-patterns observers observable observer-pattern
一位采访者问我:
什么是Observer和Observable我们何时应该使用它们?
我不知道这些术语的,所以,当我回到家,开始对谷歌搜索Observer和Observable,我发现来自不同资源的一些要点:
1)
Observable是一个类,Observer是一个接口.2)
Observable该类维护一个Observers 列表.3)当一个
Observable对象被更新时,它会调用update()每个Observers 的方法来通知它,它被改变了.
我找到了这个例子:
import java.util.Observable;
import java.util.Observer;
class MessageBoard extends Observable
{
public void changeMessage(String message)
{
setChanged();
notifyObservers(message);
}
}
class Student implements Observer
{
@Override
public void update(Observable o, Object arg)
{
System.out.println("Message board changed: " + arg);
}
}
public class MessageBoardTest
{
public static void main(String[] args)
{
MessageBoard board = new MessageBoard();
Student bob = new Student();
Student joe = new Student();
board.addObserver(bob);
board.addObserver(joe);
board.changeMessage("More Homework!");
}
}
Run Code Online (Sandbox Code Playgroud)
但我不明白为什么我们需要Observer和Observable?有什么方法setChanged()和notifyObservers(message)方法?
duf*_*ymo 254
您有一个学生和MessageBoard的具体示例.学生通过将自己添加到希望在将新消息发布到MessageBoard时得到通知的观察者列表进行注册.将消息添加到MessageBoard时,它会迭代其Observers列表并通知它们事件发生.
想想Twitter.当您说想跟随某人时,Twitter会将您添加到他们的关注者列表中.当他们发送新推文时,您会在输入中看到它.在这种情况下,您的Twitter帐户是Observer,您关注的人是Observable.
这种类比可能并不完美,因为Twitter更有可能成为调解员.但它说明了这一点.
jbx*_*jbx 56
用非常简单的术语(因为其他答案指的是所有官方设计模式,所以请查看它们以获取更多细节):
如果您想拥有一个由程序生态系统中的其他类监视的类,则表示您希望该类是可观察的.即,它的状态可能会有一些变化,你想要广播到程序的其余部分.
现在,要做到这一点,我们必须调用某种方法.我们不希望Observable类与有兴趣观察它的类紧密耦合.只要满足某些标准,它就不关心它是谁.(想象一下,这是一个广播电台,只要他们在频率上调谐FM收音机就不关心谁在听.)为此,我们使用一个称为Observer的接口.
因此,Observable类将有一个Observers列表(即实现您可能具有的Observer接口方法的实例).每当它想要广播某些内容时,它就会一个接一个地调用所有观察者的方法.
关闭这个难题的最后一件事是Observable类将如何知道谁感兴趣?所以Observable类必须提供一些机制来允许Observers注册他们的兴趣.一种方法,例如在addObserver(Observer o)内部将Observer添加到观察者列表中,以便在发生重要事件时,它循环遍历列表并调用列表中每个实例的Observer接口的相应通知方法.
这可能是在面试中他们没有问你明确地对java.util.Observer和java.util.Observable,但对通用的概念.这个概念是一种设计模式,Java恰好提供了直接开箱即用的支持,以帮助您在需要时快速实现它.因此,我建议您理解概念而不是实际的方法/类(您可以在需要时查找它们).
UPDATE
在回复您的评论时,实际java.util.Observable课程提供以下设施:
维护java.util.Observer实例列表.有兴趣获得通知的新实例可以通过添加addObserver(Observer o)和删除deleteObserver(Observer o).
维护内部状态,指定自上次通知观察者后对象是否已更改.这很有用,因为它将您所说的Observable已更改的部分与通知更改的部分分开.(例如,如果您发生了多次更改,并且您只想在流程结束时通知而不是在每个小步骤中通知,那么它很有用).这是通过完成的setChanged().因此,当你改变一些东西时,你只需要调用它Observable,你希望其余的Observers人最终知道它.
通知所有观察者具体Observable已改变状态.这是通过完成的notifyObservers().setChanged()在继续通知之前,这将检查对象是否已实际更改(即,已进行了调用).有两个版本,一个没有参数,另一个带Object参数,以防你想通知一些额外的信息.在内部发生的事情是,它只是迭代Observer实例列表并update(Observable o, Object arg)为每个实例调用方法.这告诉了Observer哪个Observable对象发生了变化(你可能会观察到多个),而额外Object arg的东西可能带来一些额外的信息(通过notifyObservers().
Mub*_*rak 36
定义
当对象之间存在一对多关系时使用观察者模式,例如,如果一个对象被修改,其依赖对象将被自动通知,并且对所有依赖对象进行相应的更改.
例子
可以说,你的永久地址被更改,然后你需要通知护照管理局和泛卡权.所以这里护照管理局和泛卡权威是观察员,你是一个主题.
在Facebook上,如果您订阅了某人,那么无论何时发生新的更新,您都会收到通知.
何时使用:
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers
= new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
Run Code Online (Sandbox Code Playgroud)
步骤1
创建主题类.
Subject.java
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
Run Code Online (Sandbox Code Playgroud)
}
第2步
创建Observer类.
Observer.java
public class BinaryObserver extends Observer{
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Binary String: "
+ Integer.toBinaryString( subject.getState() ) );
}
Run Code Online (Sandbox Code Playgroud)
第3步
创建具体的观察者类
BinaryObserver.java
public class OctalObserver extends Observer{
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: "
+ Integer.toOctalString( subject.getState() ) );
}
Run Code Online (Sandbox Code Playgroud)
}
OctalObserver.java
public class HexaObserver extends Observer{
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Hex String: "
+ Integer.toHexString( subject.getState() ).toUpperCase() );
}
Run Code Online (Sandbox Code Playgroud)
}
HexaObserver.java
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
Run Code Online (Sandbox Code Playgroud)
}
第4步
使用主题和具体观察者对象.
ObserverPatternDemo.java
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers
= new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
Run Code Online (Sandbox Code Playgroud)
}
第5步
验证输出.
第一次国家变化:15
十六进制字符串:F
八进制字符串:17
二进制字符串:1111
第二次国家变化:10
十六进制字符串:A
八进制字符串:12
二进制字符串:1010
And*_*ndy 10
它们是Observer设计模式的一部分.通常,一个或多个obervers会了解一个可观察者的变化.这是一个"事情"发生的通知,作为程序员,你可以定义"某事"的含义.
使用此模式时,您将两个实体彼此分离 - 观察者变得可插入.
小智 9
Observer aka回调在Observable注册.
它用于通知例如某些时间点发生的事件.它广泛用于Swing,Ajax,GWT,用于例如UI事件(按钮点击,文本字段更改等)的调度操作.
在Swing中,您可以在GWT中找到类似addXXXListener(Listener l)的方法(Async)回调.
由于观察者列表是动态的,观察者可以在运行时注册和取消注册.当使用接口时,它也是将观察者与观察者分离的好方法.
如果面试官要求在不使用Observer类和接口的情况下实现Observer设计模式,则可以使用以下简单示例!
interface MyObserver {
void update(MyObservable o, Object arg);
}
Run Code Online (Sandbox Code Playgroud)
class MyObservable
{
ArrayList<MyObserver> myObserverList = new ArrayList<MyObserver>();
boolean changeFlag = false;
public void notifyObservers(Object o)
{
if (hasChanged())
{
for(MyObserver mo : myObserverList) {
mo.update(this, o);
}
clearChanged();
}
}
public void addObserver(MyObserver o) {
myObserverList.add(o);
}
public void setChanged() {
changeFlag = true;
}
public boolean hasChanged() {
return changeFlag;
}
protected void clearChanged() {
changeFlag = false;
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
class MessageBoard extends MyObservable {
private String message;
public String getMessage() {
return message;
}
public void changeMessage(String message) {
this.message = message;
setChanged();
notifyObservers(message);
}
public static void main(String[] args) {
MessageBoard board = new MessageBoard();
Student bob = new Student();
Student joe = new Student();
board.addObserver(bob);
board.addObserver(joe);
board.changeMessage("More Homework!");
}
}
class Student implements MyObserver {
@Override
public void update(MyObservable o, Object arg) {
System.out.println("Message board changed: " + arg);
}
}
Run Code Online (Sandbox Code Playgroud)
"我试图弄明白,为什么我们需要Observer和Observable"
如前所述,它们提供了订阅观察者以接收可观察的自动通知的方法.
这可能有用的一个示例应用程序是数据绑定,假设您有一些用于编辑某些数据的UI,并且您希望UI在数据更新时做出反应,您可以使您的数据可观察,并订阅您的UI组件数据
Knockout.js是一个MVVM javascript框架,它有一个很棒的入门教程,可以看到更多可观察的动作,我真的建议通过本教程.http://learn.knockoutjs.com/
我还在Visual Studio 2008开始页面中找到了这篇文章(The Observer Pattern是模型视图控制器(MVC)开发的基础) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx