循环遍历共享相同超类并获得一种特定类型的不同对象的列表

时间:2018-03-03 08:00:28

标签: java refactoring observable observer-pattern observers

我正在使用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

2 个答案:

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

<强>优点:

  1. Subject未与任何其他观察员联系。
  2. 更容易添加新类型的州(价格,可用性除外)
  3. <强>缺点:

    1. 如果引入了新状态,并且必须通知所有现有观察员,则必须将其添加到所有现有观察者的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);
    }

我可以在每个因素通知之后添加一个策略。