オブザーバーモードを学ぶために5分

ここに画像を挿入説明

入門

Observerパターン:複数の視聴者が同時に対象がオブジェクトの変更されたテーマのオブジェクトを監視するには、それがすべてのオブザーバが通知されますです。

このような著者が文書を発行したマイクロチャネルパブリック数、として、すべての加入者が受け取ることになります。開閉の原則に沿って、一方でこのようなオブザーバ・モードでは、元のコードを変更することなく、新しい視聴者を追加し、放送を実現することができます。

以下オブザーバーパターンUMLダイアグラム
ここに画像を挿入説明
主題(テーマ):登録、削除、通知オブザーバ方法からオブザーバのセット定義
ConcreteSubject(特定のトピック)
オブザーバ(オブザーバ):テーマは通知を受けて作られた変化定義します
ConcreteObserver(特に観察者)

手書き観測モード

公共マイクロチャンネル番号に、例えば観察モードを書き込みます

抽象的なテーマ

public interface MySubject {

    void registerObserver(MyObserver o);

    void removeObserver(MyObserver o);

    void notifyObserver();
}

抽象オブザーバー

public interface MyObserver {
    void update(String authorName, String articleName);
}

特定のトピック

public class WeChatServer implements MySubject {

    private List<MyObserver> myObservers;
    private String authorName;
    private String articleName;

    public WeChatServer(String authorName) {
        myObservers = new ArrayList<>();
        this.authorName = authorName;
    }

    public void publishArticle(String articleName) {
        this.articleName = articleName;
        notifyObserver();
    }

    @Override
    public void registerObserver(MyObserver o) {
        myObservers.add(o);
    }

    @Override
    public void removeObserver(MyObserver o) {
        if (myObservers.contains(o)) {
            myObservers.remove(o);
        }
    }

    @Override
    public void notifyObserver() {
        myObservers.forEach(item -> {
            item.update(authorName, articleName);
        });
    }
}

特定のオブザーバー

public class WeChatClient implements MyObserver {

    private String username;

    public WeChatClient(String username) {
        this.username = username;
    }

    @Override
    public void update(String authorName, String articleName) {
        System.out.println(username + ": " + authorName + " 发了一篇文章 " + articleName);
    }
}

テストカテゴリ

public class Main {

    public static void main(String[] args) {
        WeChatServer weChatServer = new WeChatServer("Java识堂");
        WeChatClient user1 = new WeChatClient("张三");
        WeChatClient user2 = new WeChatClient("李四");
        weChatServer.registerObserver(user1);
        weChatServer.registerObserver(user2);
        weChatServer.publishArticle("《五分钟学会观察者模式》");
    }
}

出力

张三: Java识堂 发了一篇文章 《五分钟学会观察者模式》
李四: Java识堂 发了一篇文章 《五分钟学会观察者模式》

アプリケーションオブザーバーパターン

JDKはオブザーバ・モード・インタフェースを提供します

Javaは、二つのインタフェースを定義しているjava.utilパッケージ内の観察モードをサポートしています

抽象オブザーバー

public interface Observer {
    void update(Observable o, Object arg);
}

抽象的なテーマ

public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;

    public Observable() {
        obs = new Vector<>();
    }

    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
	
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}

そして、我々は以前に定義されたカザフスタンと非常によく似ていますが、より多くのスイッチング磁界の変化を、およびセキュリティスレッドを確保するために

のは、イベントオブジェクトの定義については、前述の例を書き直してみましょう

@Data
@AllArgsConstructor
public class NewArticleEvent {

    private String authorName;
    private String articleName;
}
public class WeChatServer extends Observable {

    private String authorName;
    private String articleName;

    public WeChatServer(String authorName) {
        this.authorName = authorName;
    }

    public void publishArticle(String articleName) {
        setChanged();
        this.articleName = articleName;
        notifyObservers(new NewArticleEvent(authorName, articleName));
    }
}
public class WeChatClient implements Observer {

    private String username;

    public WeChatClient(String username) {
        this.username = username;
    }

    @Override
    public void update(Observable o, Object arg) {
        NewArticleEvent event = (NewArticleEvent) arg;
        System.out.println(username + ": " + event.getAuthorName() + " 发了一篇文章 " + event.getAuthorName());
    }
}
public class Main {

    public static void main(String[] args) {
        WeChatServer weChatServer = new WeChatServer("Java识堂");
        WeChatClient user1 = new WeChatClient("张三");
        WeChatClient user2 = new WeChatClient("李四");
        weChatServer.addObserver(user1);
        weChatServer.addObserver(user2);
        weChatServer.publishArticle("《五分钟学会观察者模式》");
    }
}

上記と同じ出力

春のカスタムイベント

イベントリスナーを達成するために、春のオブザーバーモードでは、イベントリスナーは、春に達成するために、または何上記の例を変換することは比較的簡単です

イベントの種類のクラスが継承ApplicationEventに必要

@Data
public class NewArticleEvent extends ApplicationEvent {

    private String authorName;
    private String articleName;

    public NewArticleEvent(Object source, String authorName, String articleName) {
        super(source);
        this.authorName = authorName;
        this.articleName = articleName;
    }

}

私たちはApplicationListenerインタフェースまたは使用@EventListenerコメントイベントリスナーを実装することにより実現することができます

@Component
public class NewArticleEventListener implements ApplicationListener<NewArticleEvent> {

    @Override
    public void onApplicationEvent(NewArticleEvent event) {
        System.out.println(event.getAuthorName() + " 发了一篇文章 " + event.getArticleName());
    }
}
@Component
public class MyEventListener {

    @EventListener
    public void newArticleEventListener(NewArticleEvent event) {
        System.out.println(event.getAuthorName() + " 发了一篇文章 " + event.getArticleName());
    }
}

上記の例では、2つの方法、次のテストクラス開始書面で視聴者を作りました。パッケージハcom.javashitang.part6で上記のクラス

@Configuration
@ComponentScan("com.javashitang.part6")
public class AppConfig {
}
public class Main {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		context.publishEvent(new NewArticleEvent(context, "Jva识堂", "《五分钟学会观察者模式》"));
		context.close();
	}
}

この時点で、コンソール出力を見ることができます

Jva识堂 发了一篇文章 《五分钟学会观察者模式》
Jva识堂 发了一篇文章 《五分钟学会观察者模式》

まあ、今は春にカスタムイベントを持っています。オブザーバーパターンで春を達成複雑かもしれないが、基本的な考え方は、上記されます。

  • 春はApplicationEventイベントインタフェースです
  • 春はすべてのリスナーがインタフェースを実装する必要があり、ApplicationListenerイベントリスナインタフェースです
  • 春はインターフェイスを公開ApplicationEventPublisherイベントで、ApplicationContextのは、このインタフェースを実装します

春には、私たちのために、いくつかのApplicationEvent実装クラスを提供しています

  • ContextStartedEvent:イベントタイプの初期化中に発行されたのApplicationContextコンテナ
  • ContextClosedEvent:イベントタイプをシャットダウンしようとして発表された容器のApplicationContext
  • ContextRefreshedEvent:ApplicationContextの初期に発表された容器またはリフレッシュイベントタイプ

あなたは、プロジェクト定義における春のイベントの優れたアプリケーションをお知りになりたい場合は。あなたは私の以前の記事を参照することができ、我々は戦略パターンを実装するために+春のイベントを注釈を使用する方法を見て

プロジェクトあまりにも他の場合には、どのように再構築するには?

ユーザー - 春 - クラウドユーレカで定義されたイベント

我々は、すべてのユーレカは、サービス名、保存、レジストリであることを知っている- > IPアドレスの特定の関係、
マッピング関係を保存するためのConcurrentHashMap。それは確かにサービスを登録し、キャンセルする登録センター、レジスタ(登録)でユーレカに関連しているので、キャンセル(取り消し)、(更新)を更新するときは、次のコードに示すように発生した、イベントを公開します

InstanceRegistry.java

private void handleRegistration(InstanceInfo info, int leaseDuration,
		boolean isReplication) {
	log("register " + info.getAppName() + ", vip " + info.getVIPAddress()
			+ ", leaseDuration " + leaseDuration + ", isReplication "
			+ isReplication);
	publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration,
			isReplication));
}

あなたは、このようなデータの永続性の好きな情報サービスでより興味を持っているならば、あなたはこれらのイベントを聞くことができ、拡張性が特に良好ではないでしょうか?

参考ブログ

[1] https://juejin.im/post/5bcf53f351882577e5120b99#heading-8
スプリングブートプロセス全体、イベント部分がある
[2] https://www.jianshu.com/p/83693d3d0a65
[3] HTTPS://ブログ.lqdev.cn / 2018年11月6日/ springboot /チャプター-三〇から二/

公開された385元の記事 ウォンの賞賛1471 ビュー90万+

おすすめ

転載: blog.csdn.net/zzti_erlie/article/details/104736416