循环访问共享同一超类的不同对象列表并获取一种特定类型



我正在使用Java练习观察者设计模式。
我有 2 种类型的客户。
一个对价格感兴趣,而另一个对可用性感兴趣。
我正在尝试重构以下代码:

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中。

您可以在 Customer 类中编写确定其兴趣的函数:

boolean notifyOnAvailabilityChange();
boolean notifyOnPriceChange();

所以你可以把循环写成类似的东西

allObservers.filter(o -> o.notifyOnAvailabilityChange()).forEach(this::notify);

这是Turo@答案的延伸。

基本思想是,每个观察者都会告诉他们感兴趣的事件(状态变化)。然后,当事件发生时(某些状态,如价格或可用性发生变化),您通知对该事件感兴趣的人。

我将每个应通知的状态更改(如价格、可用性)称为Factor。观察者将告诉他们感兴趣的因素列表。

enum Factors {
PRICE,
AVAILABILITY
//and so on
}

观察者接口将有一个方法让观察者返回感兴趣的因素列表

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));

优点:

  1. Subject不与任何其他观察者耦合。
  2. 更容易添加新的状态类型(价格、可用性除外)

缺点:

  1. 如果引入了一个新状态,并且必须通知所有现有观察者,则必须将其添加到所有现有观察者的interestedFactors列表中。

Thanx to Turo 和 User7。这就是我所做的。我不知道这是否是最好的解决方案,因为我不仅必须向观察者订阅,而且客户也必须选择他们的兴趣。它不像订阅价格或可用性那样简单。

public enum Factors {
AVAILABILITY, PRICE
}

然后在我的客户类中,这就是我们在观察哈希图中设置兴趣的地方。

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! ");
}
}

在我的产品类中,观察者列表所在的位置。我添加了这个。

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);
}

我可以为每个因素通知添加策略。

最新更新