Observerパターン(Observerパターン)
オブジェクト、オブジェクト間の定義多くの依存関係が複数の視聴者が同時に主目的が変更された主目的を、監視することができ、それはすべての扶養家族(オブザーバー)が通知され、更新されます。
行動パターンをビロング。
時々呼ばれるオブザーバーパターンパブリッシュ・サブスクライブ(このパターンを持つように、マイクロチャンネル、QQ通知)モデル。
現実のシーン:
それをシミュレートするための2つのQQの現実シーンの間にお互いに私たちのメッセージ:
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption JDK提供的一种观察者的实现方式,我是qq主线程,我是被观察的人
* @E-Mail : [email protected]
* @Date : Created in 12:55 2020-3-15
*/
public class QQ extends Observable {
private String Name = "QQ";
private static QQ qq = null;
private QQ(){}
public static QQ getInstance(){
if(qq == null){
qq = new QQ();
}
return qq;
}
public String getName() {
return Name;
}
//发消息的人在qq上发起一个聊天,并把想要发的信息传过去
public void chat(MessageQQ message){
System.out.println(message.getQQnickName()+" 在"+this.Name+"上发了条消息,内容:"+message.getMessage());
setChanged();
notifyObservers(message);
}
}
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption 接收消息的qq,观察者,我一直观察着是否有人给我发qq消息
* @E-Mail : [email protected]
* @Date : Created in 17:17 2020-3-15
*/
public class ReceiveQQ implements Observer {
private String QQnickName;
public ReceiveQQ(String name){
this.QQnickName = name;
}
//接收消息的qq,谁发给了我消息,就要自动调用这个方法
@Override
public void update(Observable o, Object arg) {
QQ qq = (QQ) o;
MessageQQ message = (MessageQQ) arg;
System.out.println("==============");
System.out.println(this.QQnickName+" 你收到了联系人 "+message.getQQnickName()+" 的一条消息,内容:"+message.getMessage());
}
}
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption 发送消息的qq消息的人
* @E-Mail : [email protected]
* @Date : Created in 17:11 2020-3-15
*/
@Data
@AllArgsConstructor
public class MessageQQ {
private String QQnickName;
private String Message;
}
以下のコードをテストします。
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption 测试
* @E-Mail : [email protected]
* @Date : Created in 17:28 2020-3-15
*/
public class Client {
public static void main(String[] args) {
//启动qq了
QQ qq = QQ.getInstance();
//被动接收消息的人
ReceiveQQ 刀怒斩雪翼雕 = new ReceiveQQ("刀怒斩雪翼雕");
//点开要发送的老铁
qq.addObserver(刀怒斩雪翼雕);
//主动发送消息的人,要发送什么消息
MessageQQ 删库跑路 = new MessageQQ("删库跑路", "老铁,没毛病");
//回车发送给老铁
qq.chat(删库跑路);
}
}
これは、観察者jdkの方法によって達成されますが、実行する方法の原則があり、心配、リスナーは、我々はそれを聞いたことがないが、私は、このような新しいをクリックして、よりフロントエンド小さなパートナー、あるべきと考えています我々は今、それを達成するためにJavaを使用していること、イベントなどを追加します。
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption 监听器的一种包装
* @E-Mail : [email protected]
* @Date : Created in 17:50 2020-3-15
*/
@Data
@Accessors(chain = true)
public class Event {
//事件源,保存信息,事件是哪个类发起的
private Object source;
//发起这个事件要通知谁
private Object target;
//这个事件触发后要做什么,一个回调方法
private Method callback;
//事件的名称,触发的是什么事件
private String trigger;
//发生的时间
private long time;
public Event(Object target,Method callback){
this.target = target;
this.callback = callback;
}
}
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption 监听器,观察者
* @E-Mail : [email protected]
* @Date : Created in 17:55 2020-3-15
*/
public class EventLisenter {
//JDK底层的Lisenter通常也是这样设计的
protected Map<String,Event> eventMap = new HashMap<>();
//事件名称和一个目标对象来触发事件
public void addLisenter(String eventType,Object target){
try {
this.addLisenter(eventType,target,target.getClass().getMethod("on"+toUpperFirstCase(eventType),Event.class));
} catch (Exception e) {
e.printStackTrace();
}
}
public void addLisenter(String eventType, Object target, Method callback){
//注册事件
eventMap.put(eventType,new Event(target,callback));
}
//触发,只要有动作就触发
public void trigger(Event event){
event.setSource(this);
event.setTime(System.currentTimeMillis());
try {
event.getCallback().invoke(event.getTarget(),event);
} catch (Exception e) {
e.printStackTrace();
}
}
//事件名称触发
protected void trigger (String trigger){
if(!this.eventMap.containsKey(trigger)){
return;
}
trigger(this.eventMap.get(trigger));
}
//一种高效的首字母大写方法
private String toUpperFirstCase(String str){
char[] chars = str.toCharArray();
chars[0] -= 32;
return String.valueOf(chars);
}
}
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption
* @E-Mail : [email protected]
* @Date : Created in 18:21 2020-3-15
*/
public interface MouseEventType {
//单击
String ON_CLICK = "click";
//双击
String ON_DOUBLE_CLICK = "doubleClick";
}
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption 鼠标,被观察者
* @E-Mail : [email protected]
* @Date : Created in 18:22 2020-3-15
*/
public class Mouse extends EventLisenter{
public void click(){
System.out.println("调用单击方法");
this.trigger(MouseEventType.ON_CLICK);
}
public void doubleClick(){
System.out.println("调用双击给老铁一波666");
this.trigger(MouseEventType.ON_DOUBLE_CLICK);
}
}
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption 要回掉的方法
* @E-Mail : [email protected]
* @Date : Created in 18:25 2020-3-15
*/
public class MouseEvenCallback {
public void onClick(Event e){
System.out.println("======触发了单击事件======="+"\n"+e);
}
public void onDoubleClick(Event e){
System.out.println("======触发了双击事件,已经给老铁加了一个鸡腿======="+"\n"+e);
}
}
見るためにテストします。
/**
* @Author Darker
* @Note 我心净处,何处不是西天。
* @Descrption
* @E-Mail : [email protected]
* @Date : Created in 18:27 2020-3-15
*/
public class MouseEvenTest {
public static void main(String[] args) {
Mouse mouse = new Mouse();
MouseEvenCallback callback = new MouseEvenCallback();
//给鼠标添加事件
mouse.addLisenter(MouseEventType.ON_DOUBLE_CLICK,callback);
mouse.doubleClick();
}
}
イベント(
ソース=
DesigPnattern.observer.event.Mouse@71bc1ae4、(カテゴリを監視されています)
target=DesigPnattern.observer.event.MouseEvenCallback@6ed3ef1、(クラスを監視するために、イベントの対応するクラスを作ります)
コールバック=ます。public void DesigPnattern.observer.event.MouseEvenCallback.onDoubleClick(DesigPnattern.observer.event.Event)、(対応するイベントを作ります)
トリガー= nullを、
時間= 1584271173813)
上記のコードは、リスナーの実現には、当然のことながら、動的コールバックメソッドに渡すことができ、私たちは自分の外観を書くために小さなパートナーに行くことができます興味を持っているです。
さて、今私たちは、リスナーモードJDK、観測されたクラスでの初見のコードを見に戻ってきます。
それはすべての彼の視聴者であるベクトルオブザーバー、内側に入れました。
その後、我々QQの質量、あなたがグループを送っている人の選択、および各呼び出し、彼らそれぞれがメッセージを受信しているので、ということであり、それ自身の更新方法、として、彼らの更新サイクルメソッドを呼び出して、内部のすべてのオブザーバーを見つけます。
私たちは、あなたがコールバックを実行したいイベントに耳を傾けるために、リスナーの上に書いたように、私たちは何の循環を持っていない、とコールバックメソッドの位置決めを指示します。
通常使用され、スプリングは、クラスListenter Observerパターンを使用することです。
要約:
利点:
観察と観察との間の抽象的結合を作成1.
2.オブザーバーモードのサポートブロードキャスト通信
短所:
観察者との間1.は、あまりにも多くの詳細、時間がかかるを依存しており、プログラムの複雑さを増します
2.サイクルコールを防ぐため、適切に
卵を添付:Googleはプログラムの簡単な着陸オブザーバーモードを提供しています。