设计一个只监听某些属性的PropertyChangeListener

时间:2014-03-15 09:43:44

标签: java design-patterns propertychangesupport

我正在寻找以下问题的设计模式/解决方案,这与观察者模式有关,我已经研究过了。

在我的代码中,我有一个MyModel类。它有很多属性。

public class MyModel {

    private List<Flower> flowers = new ArrayList<Flower>();
    private List<Toys> toys = new ArrayList<Toys>();
    private List<Coffee> coffees = new ArrayList<Coffee>();

    private List<IBusinessEntityListener> listener =
            new ArrayList<IBusinessEntityListener>();

    public void addChangeListener(IBusinessEntityListener newListener) {
        listener.add(newListener);
    }

}

因此,实现IBusinessEntityListener的类可以注册到MyModel类。

然后我有10个以上的听众只对MyModel某些属性感兴趣。它们都实现了IBusinessEntityListener。但是我如何指定(例如使用Java Generics?)某些监听器只对Flowers感兴趣,有些只关注Toys等?

那么如何设计支持监听某些属性的类结构?

所有听众无论如何都会为操作添加更新删除实施3种方法。

2 个答案:

答案 0 :(得分:1)

对于任何类型的监听器都有一个类:

FlowerListerner implemts IBusinessEntityListener;
ToyListerner implemts IBusinessEntityListener;

和一个听众列表:

public class MyModel {

    private List<Flower> flowers = new ArrayList<Flower>();
    private List<Toys> toys = new ArrayList<Toys>();

    private List<IBusinessEntityListener> flowerListeners =
            new ArrayList<IBusinessEntityListener>();

    private List<IBusinessEntityListener> toyListeners =
            new ArrayList<IBusinessEntityListener>();

    public void addListener(IBusinessEntityListener newListener) {
        if(newListener instance of FlowerListener)
            flowerListeners.add(newListener);
        else if (newListener instance of ToyListener)
    }       toyListeners.add(newListener);

    updateFlowerListeners() { ....}
    updateToyListeners() { ....}

}

并且每个属性的任何更改都会反映给相关的侦听器。

<强>更新

另一个解决方案是你有一个感兴趣的列表 Listener Object:

Class Listener {

  private List<Class> interests;

  public Listener(List<Class> interests) {
    this.interests = interests;
  }

  public boolean isInterested(Class clazz) {
    return list.contains(clazz);
  }

  public void update() { ... }
}

a in model:

public class MyModel {

    private List<Flower> flowers = new ArrayList<Flower>();
    private List<Toys> toys = new ArrayList<Toys>();

    private List<Listener> listeners =
            new ArrayList<Listener>();

    public void addListener(Listener newListener) {
        listeners.add(newListener);
    }     

    updateFlowerListeners() {
        for(Listener l : listerners) {
           if(l.isInterested(Flower.class)
               l.update();       
    }

    updateToyListeners() { ...  }

}

答案 1 :(得分:1)

如何应用Extrinsic Visitor模式?

定义属性的接口:

public interface ListenableProperty {
    // Degenerate interface for listeners
    public interface Listener {}

    public void acceptUpdate(Listener listener);
}

然后为每个属性实现一个类,并为每个属性实现一个Listener接口,并在模型中使用类似的东西:

public class MyModel {
    public static class FlowersProperty implements ListenableProperty {
        public interface Listener extends ListenableProperty.Listener {
            public void update(FlowersProperty p);
        }

        @Override
        public void acceptUpdate(ListenableProperty.Listener listener) {
            if (listener instanceof FlowersProperty.Listener) {
                Listener myListenerType = (Listener)listener;
                myListenerType.update(this);
            }
        }

        // some property accessors here
    }

    public static class ToysProperty implements ListenableProperty {
        public interface Listener extends ListenableProperty.Listener {
            public void update(ToysProperty p);
        }

        @Override
        public void acceptUpdate(ListenableProperty.Listener listener) {
            if (listener instanceof ToysProperty.Listener) {
                Listener myListenerType = (Listener)listener;
                myListenerType.update(this);
            }
        }

        // some property accessors here
    }

    private FlowersProperty flowers = new FlowersProperty();
    private ToysProperty toys = new ToysProperty();
    private List<ListenableProperty> properties = new ArrayList();

    // CopyOnWrite so that listeners can remove themselves during update if desired
    private List<ListenableProperty.Listener> listeners = 
            new CopyOnWriteArrayList<>();

    // Convenience interface for implementors that want all properties
    public interface AllPropertiesListener extends
        FlowersProperty.Listener,
        ToysProperty.Listener 
    {}

    public MyModel() {
        properties.add(flowers);
        properties.add(toys);
    }

    public void addListener(ListenableProperty.Listener l) {
        if (!listeners.contains(l)) {
            listeners.add(l);
        }
    }

    private void updateAll() {
        for (ListenableProperty p : properties) {
            for (ListenableProperty.Listener l : listeners) {
                p.acceptUpdate(l);
            }
        }
    }

    private void updateToys() {
        for (ListenableProperty.Listener l : listeners) {
            toys.acceptUpdate(l);
        }
    }

    private void updateFlowers() {
        for (ListenableProperty.Listener l : listeners) {
            flowers.acceptUpdate(l);
        }
    }
}

然后,侦听器可以根据需要实现尽可能多的侦听器接口,或者通过便捷接口MyModel.AllPropertiesListener

实现所有这些接口。

您还可以将各个属性的更新例程移动到属性本身。