Design Patterns eight: the observer mode (Observer)

In the real world, many objects are not independent, where the behavior of an object changes may result in one or more of the behavior of other objects also changed. For example, when the price of a commodity prices will lead to some businesses happy, sad and consumers; also, when we drove into the intersection, a red light will stop, the green light will come across the line. There are many such examples, such as stock prices and weather forecasts with the audience, the thief and the police and other investors, the public micro-channel number and the micro-channel users, Bureau of Meteorology.

In the software world the same way, for example, the relationship between the data in Excel and line charts, pie charts, bar charts; the relationship between model and view the MVC mode; event model event source and an event handler. All of these, if the observer mode to achieve is very convenient.

The definition and characteristics of the model

Defined observers (Observer) mode: refers to the presence of many dependencies among a plurality of objects, when a state of the object changes, all objects that depend on it have been notified and updated automatically. This mode is sometimes referred to publish - subscribe model, model - view mode, it is the object behavioral patterns.

Observer pattern is an object behavioral pattern, its main advantages are as follows.

  1. Reducing the coupling between the object and the observer, abstract coupling between the two.
  2. We have set up a trigger mechanism between the target and the observer.


Its main drawback as follows.

  1. Dependencies between the target and the observer is not completely removed, but there may be a circular reference.
  2. When an object many observers, the conference notification spend a lot of time, it affects the efficiency of the program.

Architecture and Implementation Model

Should pay attention to when implementing the observer pattern can not be called directly between the specific target audience and specific observer objects will keep the tight coupling between them, in violation of the principles of object-oriented design.

1. Structure Model

The main role of the observer mode are as follows.

  1. Abstract topics (Subject) Role: also known as an abstract object classes, which provides aggregation and increase class to hold a viewer object, delete observer object methods, abstract methods and notification of all observers.
  2. Specific topics (Concrete Subject) Role: also known as specific target class that implements the abstract goal of the notification method, when the internal state specific theme changes, notify all registered observers object.
  3. Abstract observer (Observer) role: it is an abstract class or interface, which includes an updated his abstract method, when receiving change notification specific theme is called.
  4. Specific observer (Concrete Observer) roles: the abstract methods defined in the abstract observer implemented in order to update their status when obtaining change notification goals.


Observer pattern configuration diagram shown in Fig.
 

                            FIG observer pattern structure
 

2. Mode of realization

Observer pattern codes are as follows:

package observer;
import java.util.*;
public class ObserverPattern
{
    public static void main(String[] args)
    {
        Subject subject=new ConcreteSubject();
        Observer obs1=new ConcreteObserver1();
        Observer obs2=new ConcreteObserver2();
        subject.add(obs1);
        subject.add(obs2);
        subject.notifyObserver();
    }
}
//抽象目标
abstract class Subject
{
    protected List<Observer> observers=new ArrayList<Observer>();   
    //增加观察者方法
    public void add(Observer observer)
    {
        observers.add(observer);
    }    
    //删除观察者方法
    public void remove(Observer observer)
    {
        observers.remove(observer);
    }   
    public abstract void notifyObserver(); //通知观察者方法
}
//具体目标
class ConcreteSubject extends Subject
{
    public void notifyObserver()
    {
        System.out.println("具体目标发生改变...");
        System.out.println("--------------");       
       
        for(Object obs:observers)
        {
            ((Observer)obs).response();
        }
       
    }          
}
//抽象观察者
interface Observer
{
    void response(); //反应
}
//具体观察者1
class ConcreteObserver1 implements Observer
{
    public void response()
    {
        System.out.println("具体观察者1作出反应!");
    }
}
//具体观察者1
class ConcreteObserver2 implements Observer
{
    public void response()
    {
        System.out.println("具体观察者2作出反应!");
    }
}

Program results are as follows: 

具体目标发生改变...
--------------
具体观察者1作出反应!
具体观察者2作出反应!

Mode of application examples

[Example 1] using the observer pattern design a program to analyze the effect "exchange rate" margin of appreciation or depreciation of the import company imported product costs or export companies export products and the company's earnings.

Analysis: When the "exchange rate" appreciation, import companies reduce the cost of imported products and margin improvement, the company's export products export revenue and lower profit margins; when the "exchange rate" devaluation, import company imported products and the cost of upgrading lower profit margins, export companies export products to enhance revenue and margin improvement.

Here's the exchange rate (Rate) target class is an abstract class that contains the saved observer (Company) The List and add / remove observer methods, and abstract method change related to exchange rate changes (int number); and the RMB exchange rate (RMBrate ) specific objectives class, which implements the change of the parent class (int number) method, i.e., when the exchange rate is changed by the relevant company; (company) is an abstract class observer, which defines an abstract method related exchange reactions response (int number); import company (ImportCompany) class and an outlet Corporation (ExportCompany) viewer class is a concrete class that implement the parent response (int number) method, i.e., when they receive a notification of a change in exchange rate accordingly. Figure 2 is a structural view.
 

                        AAE aººae ° ± caaecaºcc »aea¾


Code is as follows:

package observer;
import java.util.*;
public class RMBrateTest
{
    public static void main(String[] args)
    {
        Rate rate=new RMBrate();         
        Company watcher1=new ImportCompany(); 
        Company watcher2=new ExportCompany();           
        rate.add(watcher1); 
        rate.add(watcher2);           
        rate.change(10);
        rate.change(-9);
    }
}
//抽象目标:汇率
abstract class Rate
{
    protected List<Company> companys=new ArrayList<Company>();   
    //增加观察者方法
    public void add(Company company)
    {
        companys.add(company);
    }    
    //删除观察者方法
    public void remove(Company company)
    {
        companys.remove(company);
    }   
    public abstract void change(int number);
}
//具体目标:人民币汇率
class RMBrate extends Rate 
{
    public void change(int number)
    {       
        for(Company obs:companys)
        {
            ((Company)obs).response(number);
        }       
    }
}
//抽象观察者:公司
interface Company
{
    void response(int number);
}
//具体观察者1:进口公司 
class ImportCompany implements Company 
{
    public void response(int number) 
    {
        if(number>0)
        {
            System.out.println("人民币汇率升值"+number+"个基点,降低了进口产品成本,提升了进口公司利润率。"); 
        }
        else if(number<0)
        {
              System.out.println("人民币汇率贬值"+(-number)+"个基点,提升了进口产品成本,降低了进口公司利润率。"); 
        }
    } 
} 
//具体观察者2:出口公司
class ExportCompany implements Company 
{
    public void response(int number) 
    {
        if(number>0)
        {
            System.out.println("人民币汇率升值"+number+"个基点,降低了出口产品收入,降低了出口公司的销售利润率。"); 
        }
        else if(number<0)
        {
              System.out.println("人民币汇率贬值"+(-number)+"个基点,提升了出口产品收入,提升了出口公司的销售利润率。"); 
        }
    } 
}

Program results are as follows: 

人民币汇率升值10个基点,降低了进口产品成本,提升了进口公司利润率。
人民币汇率升值10个基点,降低了出口产品收入,降低了出口公司的销售利润率。
人民币汇率贬值9个基点,提升了进口产品成本,降低了进口公司利润率。
人民币汇率贬值9个基点,提升了出口产品收入,提升了出口公司的销售利润率。

 Observer pattern in software concurrency and most frequently used form of event processing program design, all components of the form are "event source", that is the target object, and the object is an event handler class specific observation those who object. Below a school bell event handler as an example, in Windows' event handling model "works.

[Example 2] event handler using the observer pattern design of a school bell.

Analysis: this example, the school "bell" is an event source and target, "teacher" and "student" is a specific event listener and observer, "ringtone" is the event class. Students and teachers came to school the teaching area, will pay attention to the school's bell, called the event binding; when school hours or after school hours that will trigger the bell sound, then generates a "bell" events; students and teachers heard the bell They will start school or class, called event handling. Examples of this are well suited for use observer pattern, Figure 3 shows the event model school ringtones.
 

                                   School bell event model diagram


Now with "observer mode" to achieve the event handling model. First, define a ringing event (RingEvent) class, which records the type (class ring / class ring) ringtone; redefinition of a school bell (BellEventSource) class, which is the event source, objective observer class, which contains a listener container listener, you can bind listener (student or teacher), and there are ways to generate tones events and inform listeners of all; then, define the sound event listener (BellEventListener) class, which is an abstract observer, it Ringtones contains event handler method heardBell (RingEvent e); and finally, the definition of the class teacher (TeachEventListener) and student categories (StuEventListener), which is an event listener, is a specific observer, heard the bell would go to class or after class. Figure 4 shows the structure of the school bell event handler.
 

                      School bell block diagram of an event handler


Code is as follows:

package observer;
import java.util.*;
public class BellEventTest
{
    public static void main(String[] args)
    {
        BellEventSource bell=new BellEventSource();    //铃(事件源)    
        bell.addPersonListener(new TeachEventListener()); //注册监听器(老师)
        bell.addPersonListener(new StuEventListener());    //注册监听器(学生)
        bell.ring(true);   //打上课铃声
        System.out.println("------------");   
        bell.ring(false);  //打下课铃声
    }
}
//铃声事件类:用于封装事件源及一些与事件相关的参数
class RingEvent extends EventObject
{   
    private static final long serialVersionUID=1L;
    private boolean sound;    //true表示上课铃声,false表示下课铃声
    public RingEvent(Object source,boolean sound)
    {
        super(source);
        this.sound=sound;
    }   
    public void setSound(boolean sound)
    {
        this.sound=sound;
    }
    public boolean getSound()
    {
        return this.sound;
    }
}
//目标类:事件源,铃
class BellEventSource
{    
    private List<BellEventListener> listener; //监听器容器
    public BellEventSource()
    { 
        listener=new ArrayList<BellEventListener>();        
    }
    //给事件源绑定监听器 
    public void addPersonListener(BellEventListener ren)
    { 
        listener.add(ren); 
    }
    //事件触发器:敲钟,当铃声sound的值发生变化时,触发事件。
    public void ring(boolean sound)
    {
        String type=sound?"上课铃":"下课铃";
        System.out.println(type+"响!");
        RingEvent event=new RingEvent(this, sound);     
        notifies(event);    //通知注册在该事件源上的所有监听器                
    }   
    //当事件发生时,通知绑定在该事件源上的所有监听器做出反应(调用事件处理方法)
    protected void notifies(RingEvent e)
    { 
        BellEventListener ren=null; 
        Iterator<BellEventListener> iterator=listener.iterator(); 
        while(iterator.hasNext())
        { 
            ren=iterator.next(); 
            ren.heardBell(e); 
        } 
    }
}
//抽象观察者类:铃声事件监听器
interface  BellEventListener extends EventListener
{
    //事件处理方法,听到铃声
    public void heardBell(RingEvent e);
}
//具体观察者类:老师事件监听器
class TeachEventListener implements BellEventListener
{
    public void heardBell(RingEvent e)
    {        
        if(e.getSound())
        {
            System.out.println("老师上课了...");           
        }
        else
        {
            System.out.println("老师下课了...");   
        }          
    }
}
//具体观察者类:学生事件监听器
class StuEventListener implements BellEventListener
{
    public void heardBell(RingEvent e)
    {        
        if(e.getSound())
        {
            System.out.println("同学们,上课了...");           
        }
        else
        {
            System.out.println("同学们,下课了...");   
        }          
    }
}

Program results are as follows: 

上课铃响!
老师上课了...
同学们,上课了...
------------
下课铃响!
老师下课了...
同学们,下课了...

 

Application of scene modes

For the following situations seen by the observer pattern analysis and application of the foregoing.

  1. Many relationship between objects, an object's state changes will affect other objects.
  2. When an abstract model has two aspects, one aspect of which is dependent on the other hand, the both of these may be encapsulated in a separate object so that they can be independently varied and reuse.

Extended mode

In Java, the class and by java.util.Observable java.util.Observer interface defines the observer pattern, as long as they achieve subclasses can write the observer pattern instance.

1. Observable class

Observable class is an abstract class goal, it has a Vector vector used to hold all observers object to be notified, let's introduce its most important three methods.

  1. void addObserver (Observer o) Methods: a viewer for adding a new object to the vector.
  2. void notifyObservers (Object arg) method: call update all observers object vector. The method of informing them that data changes. Usually the later addition of the first vector of the observer to be notified.
  3. void setChange () method: used to set a boolean internal flag, indicating the target object changes. When it is true, notifyObservers () will notify the viewer.

2. Observer Interface

Observer interface is an abstract viewer, which monitors changes in the target object when the target object is changed, the viewer is notified, and calls void update (Observable o, Object arg ) method, the corresponding work.

[Example 3] Using Observable Observer interface classes and the observer pattern instance crude oil futures.

Analysis: When crude oil prices, the short side sad, and more Fangju Xing; when oil prices fall, empty Fangju Xing, multi sad. Abstract goal in the present example (Observable) class defined in Java, a subclass can be defined directly, i.e., crude (OilFutures) class, which is a concrete target class, a class is defined SetPriCe (float price) method, when crude data call parent class changes notifyObservers (Object arg) to notify all observers; in the present example the abstract interface to the observer (observer) have been defined in Java, as long as the subclass is defined, i.e. the specific observation by category (including multi-party-based and space-based Bull Bear), and implement update (Observable o, Object arg) method may be. Figure 5 shows the structure of FIG.
 

                    Crude observer pattern configuration example of FIG.


Code is as follows:

 

package observer;
import java.util.Observer;
import java.util.Observable;
public class CrudeOilFutures
{
    public static void main(String[] args)
    {
        OilFutures oil=new OilFutures();
        Observer bull=new Bull(); //多方
        Observer bear=new Bear(); //空方
        oil.addObserver(bull);
        oil.addObserver(bear);
        oil.setPrice(10);
        oil.setPrice(-8);
    }
}
//具体目标类:原油期货
class OilFutures extends Observable
{
    private float price;   
    public float getPrice()
    {
        return this.price; 
    }
    public void setPrice(float price)
    {
        super.setChanged() ;  //设置内部标志位,注明数据发生变化 
        super.notifyObservers(price);    //通知观察者价格改变了 
        this.price=price ; 
    }
}
//具体观察者类:多方
class Bull implements Observer
{   
    public void update(Observable o,Object arg)
    {
        Float price=((Float)arg).floatValue();
        if(price>0)
        {
            System.out.println("油价上涨"+price+"元,多方高兴了!");
        }
        else
        {
            System.out.println("油价下跌"+(-price)+"元,多方伤心了!");
        }
    }
}
//具体观察者类:空方
class Bear implements Observer
{   
    public void update(Observable o,Object arg)
    {
        Float price=((Float)arg).floatValue();
        if(price>0)
        {
            System.out.println("油价上涨"+price+"元,空方伤心了!");
        }
        else
        {
            System.out.println("油价下跌"+(-price)+"元,空方高兴了!");
        }
    }
}

 Program results are as follows:

油价上涨10.0元,空方伤心了!
油价上涨10.0元,多方高兴了!
油价下跌8.0元,空方高兴了!
油价下跌8.0元,多方伤心了!

 

Published 136 original articles · won praise 6 · views 1542

Guess you like

Origin blog.csdn.net/weixin_42073629/article/details/104437861