我正在使用Java练习观察者设计模式。
我有两种类型的客户。
一个人对价格感兴趣而另一个人对可用性感兴趣。
我正在尝试重构以下代码:
public void setAvailable(boolean available) {
this.available = available;
if (this.available == true)
for (Iobserver o : allObservers) {
if (o instanceof CustomerAvailabilityObserver)
notify(o);
}
}
有人告诉我,无论何时我使用instanceof
,我的代码中都会有一些难以修复的气味。
如何重写for循环的任何想法?顺便说一句,观察者存储在ArrayList
。
答案 0 :(得分:1)
这是Turo @的答案的延伸。
基本思想是每个观察者都会告诉他们感兴趣的事件(状态变化)。然后,当事件发生时(某些状态如价格或可用性变化),您只通知 那些对此事件感兴趣的人。
我将每个应通报状态更改(例如价格,可用性)称为Factor
。观察员将告诉他们感兴趣的因素列表。
enum Factors {
PRICE,
AVAILABILITY
//and so on
}
Observer接口将有一个方法让Observer返回感兴趣的因子列表
interface IObserver {
List<Factors> interestedFactors();
//other existing methods
}
示例观察员:
class Observer1 implements IObserver {
@Override
public List<Factors> interestedFactors() {
return ImmutableList.of(Factors.PRICE);
}
}
class Observer2 implements IObserver {
@Override
public List<Factors> interestedFactors() {
//Some might be interested in multiple states
return ImmutableList.of(Factors.PRICE, Factors.AVAILABILITY);
}
}
状态发生变化后,您可以过滤对该状态感兴趣的观察者并通知他们。
allObservers.stream()
.filter(observer -> observer.interestedFactors().contains(Factors.<whatever_the_cuurent_state_change_is>))
.forEach(observer -> notify(observer));
<强>优点:强>
Subject
未与任何其他观察员联系。<强>缺点:强>
interestedFactors
列表中。答案 1 :(得分:0)
Thanx to Turo和User7。这就是我做的。我不知道它是否是最好的解决方案,因为不仅我必须为观察者提供服务,而且客户也必须选择他们的兴趣。它不像订阅价格或可用性那样直截了当。
public enum Factors {
AVAILABILITY, PRICE
}
然后在我的Customer Class中,我们在观察hashmap中设置了兴趣。
public class Customer implements Iobserver {
String name;
String email;
private EnumMap<Factors, Boolean> observations = new EnumMap<Factors, Boolean>(Factors.class);
public Customer(String name, String email) {
this.name = name;
this.email = email;
for (Factors factor : Factors.values()) {
observations.put(factor, false);
}
}
public void setObsevation(Factors factor, Boolean isInterested) {
observations.put(factor, isInterested);
}
public boolean getObservation(Factors factor) {
return observations.get(factor);
}
public void update(Product p, Factors factor) {
System.out.println("Dear customer " + this.name + ", the " + factor.toString().toLowerCase() + " of "+ p.getProduct() + " has changed! ");
}
}
在我的Product类中,观察者列表所在的位置。我添加了这个。
public void setPrix(float prix) {
if (prix != this.prix) {
this.prix = prix;
for (Iobserver o : allObservers) {
if (o.getObservation(Factors.PRICE)) {
notify(o,Factors.PRICE);
}
}
}
}
public void setAvailable(boolean available) {
this.available = available;
if (this.available == true)
for (Iobserver o : allObservers) {
if (o.getObservation(Factors.AVAILABILITY))
notify(o,Factors.AVAILABILITY);
}
}
public void notify(Iobserver o, Factors factor) {
o.update(this,factor);
}
我可以在每个因素通知之后添加一个策略。