设计模式-观察者模式

观察者模式

关键要素:事件,事件发布器,事件监听器

简单实现

  • 一个类中存一个事件列表,这个类相当于事件发布器
  • 创建事件的时候,将事件保存到这个发布器的事件类表中,然后调用事件发布器的通知方法,循环调用 事件的方法

发布器 Subject

public class Subject {
    private List<Observer> observers = new ArrayList<>();
    public void attach(Observer observer) {
        this.observers.add(observer);
    }
    public void notifyAllObserver(){
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

事件抽象类 Observer

public abstract class Observer {
    protected Subject subject;
    public abstract void update();
}

事件实现类 OrderOberser

public class OrderObserver extends Observer{
    public OrderObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }
    @Override
    public void update() {
        System.out.println("orderObserver update");
    }
}

通知事件

public class MainClazz {
    public static void main(String[] args) {
        Subject subject = new Subject();
        new OrderObserver(subject);
        subject.notifyAllObserver();
    }
}

领域事件应用

可以通过观察者模式实现领域事件

  • 需要三个元素
    • 事件 DomainEvent
    • 事件发布器 DomainEventPublisher
    • 事件监听器 DomainEventListener

事件抽象

public abstract class DomainEvent {
    public abstract Date createDate();
    public abstract String content();
}

事件监听接口

public interface DomainEventListener<T extends DomainEvent> {
    void handler(T event);
}

事件发布器

public class DomainEventPublisher {
    private static ConcurrentHashMap<Class<? extends DomainEvent>, List<DomainEventListener<? extends DomainEvent>>> listenerMap = new ConcurrentHashMap<>();

    public synchronized static <T extends DomainEvent> void register(Class<T> clazz, DomainEventListener<T> listener) {
        List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(clazz);
        if (listenerList == null) {
            listenerList = new ArrayList<>();
        }
        listenerList.add(listener);
        listenerMap.put(clazz, listenerList);
    }

    public static <T extends DomainEvent> void publish(T event) {
        List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(event.getClass());
        if (listenerList != null) {
            for (DomainEventListener listener : listenerList) {
                listener.handler(event);
            }
        }
    }
}

使用示例

事件实现

public class TestEvent extends DomainEvent{

    private String flowNo;

    @Override
    public Date createDate() {
        return new Date();
    }

    @Override
    public String content() {
        return "事件内容";
    }

    public void getFlowNo(){
        System.out.println("该事件自己的事件逻辑");
    }

}

监听器实现

public class TestListener implements DomainEventListener<TestEvent>{

    public TestListener() {
        DomainEventPublisher.register(TestEvent.class, this);
    }

    @Override
    public void handler(TestEvent event) {
        event.getFlowNo();
        String content = event.content();
        System.out.println("content = " + content);
    }
}

调用

public class MainClazz {
    public static void main(String[] args) {
        TestListener testListener = new TestListener();
        DomainEventPublisher.publish(new TestEvent());
    }
}

如果想要异步执行事件,可以在事件发布器中定义一个线程池,使用线程池执行事件的处理

public class DomainEventPublisher {

    private static Executor executor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>());

    private static ConcurrentHashMap<Class<? extends DomainEvent>, List<DomainEventListener<? extends DomainEvent>>> listenerMap = new ConcurrentHashMap<>();

    public synchronized static <T extends DomainEvent> void register(Class<T> clazz, DomainEventListener<T> listener) {
        List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(clazz);
        if (listenerList == null) {
            listenerList = new ArrayList<>();
        }
        listenerList.add(listener);
        listenerMap.put(clazz, listenerList);
    }

    public static <T extends DomainEvent> void publish(T event) {
        List<DomainEventListener<? extends DomainEvent>> listenerList = listenerMap.get(event.getClass());
        if (listenerList != null) {
            for (DomainEventListener listener : listenerList) {
                executor.execute(()->{
                    listener.handler(event);
                });
            }
        }
    }
}

Guava EventBus

谷歌的eventbus也是一种观察者模式,可以用来实现相同的功能

事件发布器

@Component
public class GuavaPublisher {

    private EventBus eventBus = new EventBus("test");

    @Autowired
    private TestListener testListener;

    @PostConstruct
    public void init(){
        eventBus.register(testListener);
    }

    public void postEvent(){
        eventBus.post(new TestEvent());
    }

}

监听器
监听器需要在一个方法上使用 @Subscribe 注解

@Component
public class TestListener {

    @Subscribe
    public void handler(TestEvent event){
        String content = event.getContent();
        System.out.println("content = " + content);
    }

}

事件类

public class TestEvent {
    private String content;
    public String getContent(){
        return "content";
    }
}

如果想要使用异步,可以使用 AsyncEventBus

private AsyncEventBus eventBus = new AsyncEventBus(new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>()));

你可能感兴趣的:(设计模式,观察者模式,java)