观察者模式:用状态通知
Observer pattern: notify with state
我在网上看到的例子只给 Observable 对象 notifyObservers()
方法。如果我还想将一些数据传递给观察者,以便他们知道他们是否应该对此做出反应怎么办?观察者模式是否允许像 maybe:
这样传递数据
notifyObservers(Event e)
.
或者也许观察者自己应该拉动变化?也许像:
notifyObservers() -> call observer.update()
然后每个观察者决定新数据是否与他们相关,observable.getData()
。但是,对于这种方法,我不清楚如何只获取发生变化的数据(如果需要的话)。
编辑,示例:
说我想开一家有运营商、客户和出租车的出租车公司。根据 @Pritam Banerjee 的 回答,我会说出租车公司是运营商和客户之间的调解人(例如,为什么 - 客户可以通过 phone 或在线呼叫出租车) .那我的运营商就是主体,出租车就是观察者
Operator ---observes---> TaxiFirm
TaxiFirm(waits for client) ---notifies one---> Operator
(公司选择负责的运营商,并将客户传递给运营商)
Taxi ---observes all---> Operators
(需要在这里推送数据,如果出租车被占用,则无法接收新客户)
Taxi ---notifies---> Operator
(如果出租车可以接受客户,它会通知运营商这件事,我不关心任何竞争条件,因为这个事件将被手动触发。另外,也许出租车应该通知公司和不是运营商?)
我认为 TaxiFirm 可能不需要将客户传递给运营商,但考虑到现实生活,真正与客户对话的是运营商...
我写下了我的思考过程,请帮我弄清楚这个模型的架构。
您可以将观察者设计模式与中介者模式结合使用,这样应用程序也可以向其他相关应用程序订阅和发布数据。
有关此示例,您可以查看 here。
有关中介器设计模式的更多详细信息,您可以阅读此article。
当然,ObserverPattern 允许您通过其 notify
方法传递信息。如果出租车需要客户信息,您可以通过:
observer.notify(ClientInfo info)
当然,Observers 也可以请求信息:
observer.notify()
void notify() {
update();
}
两者都是可能的,但是,我不会说你真的有 ObserverPattern 在这里。根据这个模式,Subject 只是通知 all 个 Observers。但是你描述的是 Subject 应该通知其中一辆出租车,等待它的响应(如果出租车已经载客),然后可能通知下一辆出租车。您可以将其称为 ObserverPattern 的变体,但它是不同的。
一个简单的建议,供您入门:
class 运算符:
List<Taxi> taxis;
boolean chooseTaxi(RideNumber rideNumber) {
for (Taxi taxi : taxis) {
boolean isAccepted = taxi.notify(this, rideNumber);
if (isAccepted) {
markTaxiRideAsAccepted(taxi, rideNumber);
return true;
}
}
return false; // No taxi accepted the ride.
}
class出租车:
boolean notify(Operator operator, RideNumber rideNumber) {
if (isTaxiAlreadyCarryingPassenger()) return false;
ClientInfo clientInfo = operator.getClientInfo(this, rideNumber);
startClientProcess(clientInfo);
return true;
}
注意:RideNumber
只是一个识别码,出租车稍后会用它来向运营商请求客户信息。您可以改为通过 notify 方法发送 clientInfo
,但随后所有出租车都会获得此信息,这对安全性来说很糟糕,并且还可能造成混淆(发送不应使用的信息)。
更新:
如果这是家庭作业,并且您必须使用确切的 ObserverPattern,您可以这样做:
class 运算符:
List<Taxi> taxis;
void notifyAllTaxis(RideNumber rideNumber) {
for (Taxi taxi : taxis) {
taxi.notify(this, rideNumber);
}
}
}
ClientInfo getClientInfo(this, rideNumber) {
if (isRideNotYetAccepted(rideNumber)) {
markRideAsAccepted(taxi, rideNumber);
return getClientInfo(rideNumber);
}
else return null;
}
class出租车:
void notify(Operator operator, RideNumber rideNumber) {
if (!isTaxiAlreadyCarryingPassenger()) {
ClientInfo clientInfo = operator.getClientInfo(this, rideNumber);
if (clientInfo != null) startClientProcess(clientInfo);
}
}
我在网上看到的例子只给 Observable 对象 notifyObservers()
方法。如果我还想将一些数据传递给观察者,以便他们知道他们是否应该对此做出反应怎么办?观察者模式是否允许像 maybe:
notifyObservers(Event e)
.
或者也许观察者自己应该拉动变化?也许像:
notifyObservers() -> call observer.update()
然后每个观察者决定新数据是否与他们相关,observable.getData()
。但是,对于这种方法,我不清楚如何只获取发生变化的数据(如果需要的话)。
编辑,示例:
说我想开一家有运营商、客户和出租车的出租车公司。根据 @Pritam Banerjee 的 回答,我会说出租车公司是运营商和客户之间的调解人(例如,为什么 - 客户可以通过 phone 或在线呼叫出租车) .那我的运营商就是主体,出租车就是观察者
Operator ---observes---> TaxiFirm
TaxiFirm(waits for client) ---notifies one---> Operator
(公司选择负责的运营商,并将客户传递给运营商)
Taxi ---observes all---> Operators
(需要在这里推送数据,如果出租车被占用,则无法接收新客户)
Taxi ---notifies---> Operator
(如果出租车可以接受客户,它会通知运营商这件事,我不关心任何竞争条件,因为这个事件将被手动触发。另外,也许出租车应该通知公司和不是运营商?)
我认为 TaxiFirm 可能不需要将客户传递给运营商,但考虑到现实生活,真正与客户对话的是运营商...
我写下了我的思考过程,请帮我弄清楚这个模型的架构。
您可以将观察者设计模式与中介者模式结合使用,这样应用程序也可以向其他相关应用程序订阅和发布数据。
有关此示例,您可以查看 here。
有关中介器设计模式的更多详细信息,您可以阅读此article。
当然,ObserverPattern 允许您通过其 notify
方法传递信息。如果出租车需要客户信息,您可以通过:
observer.notify(ClientInfo info)
当然,Observers 也可以请求信息:
observer.notify()
void notify() {
update();
}
两者都是可能的,但是,我不会说你真的有 ObserverPattern 在这里。根据这个模式,Subject 只是通知 all 个 Observers。但是你描述的是 Subject 应该通知其中一辆出租车,等待它的响应(如果出租车已经载客),然后可能通知下一辆出租车。您可以将其称为 ObserverPattern 的变体,但它是不同的。
一个简单的建议,供您入门:
class 运算符:
List<Taxi> taxis;
boolean chooseTaxi(RideNumber rideNumber) {
for (Taxi taxi : taxis) {
boolean isAccepted = taxi.notify(this, rideNumber);
if (isAccepted) {
markTaxiRideAsAccepted(taxi, rideNumber);
return true;
}
}
return false; // No taxi accepted the ride.
}
class出租车:
boolean notify(Operator operator, RideNumber rideNumber) {
if (isTaxiAlreadyCarryingPassenger()) return false;
ClientInfo clientInfo = operator.getClientInfo(this, rideNumber);
startClientProcess(clientInfo);
return true;
}
注意:RideNumber
只是一个识别码,出租车稍后会用它来向运营商请求客户信息。您可以改为通过 notify 方法发送 clientInfo
,但随后所有出租车都会获得此信息,这对安全性来说很糟糕,并且还可能造成混淆(发送不应使用的信息)。
更新:
如果这是家庭作业,并且您必须使用确切的 ObserverPattern,您可以这样做:
class 运算符:
List<Taxi> taxis;
void notifyAllTaxis(RideNumber rideNumber) {
for (Taxi taxi : taxis) {
taxi.notify(this, rideNumber);
}
}
}
ClientInfo getClientInfo(this, rideNumber) {
if (isRideNotYetAccepted(rideNumber)) {
markRideAsAccepted(taxi, rideNumber);
return getClientInfo(rideNumber);
}
else return null;
}
class出租车:
void notify(Operator operator, RideNumber rideNumber) {
if (!isTaxiAlreadyCarryingPassenger()) {
ClientInfo clientInfo = operator.getClientInfo(this, rideNumber);
if (clientInfo != null) startClientProcess(clientInfo);
}
}