preface

In the previous article, we learned Memento patterns and state patterns of behavioral patterns. In this paper, we will learn the last two behavioral patterns, Observer Pattern and NullObject Pattern.

Observer model

Introduction to the

The observer pattern is also called Publish/Subscribe, Model/View, Source/Listener or Dependents. The observer pattern defines a one-to-many dependency that allows multiple observer objects to listen on a subject object simultaneously. This topic object notifies all observer objects when it changes in state, enabling them to update themselves automatically. Its main purpose is to define a one-to-many dependency between objects, so that when an object’s state changes, all dependent objects are notified and automatically updated.

The Observer pattern is mainly composed of four roles: Abstract Subject, ConcreteSubject, Abstract Observer and ConcreteObserver.

  • Abstract Subject: It stores references to all observer objects in an aggregate, and each Subject can have any number of observers. Abstract topics provide an interface to add and remove observer objects.
  • ConcreteSubject: Store the relevant state into a concrete observer object; All registered observers are notified when the internal status of a specific topic changes.
  • Abstract Observer role: Primarily responsible for restoring the state of the object from the memo object.

Here’s an example:

Let’s use an example to illustrate. When we watch TV series on the video website, there is usually a subscription function. If we subscribe to a certain TV series, the updated news will be pushed to the subscribers when the TV series is updated. If the subscribers cancel the subscription or do not subscribe, the users will not receive the news. Then we can use the memo pattern for development based on this scenario.

Start by defining an abstract theme that brings together observers (subscribers) for additions, deletions, and notifications. The code is as follows:


interface BangumiSubject{
   
   void toThem(UserObserver user);

   void callOff(UserObserver user);

   void notifyUser();
}

Copy the code

We then define an abstract observer, with the main method update, which is used to update when notified, as in the case of the user.

The code is as follows:

interface UserObserver{
   
   void update(String bangumi);
   
   String getName();
}

Copy the code

We then define a concrete topic that implements the abstract topic (BangumiSubject) interface and holds the observer’s information through a List collection, traversing the notification when it is needed. The code is as follows:

	class  Bangumi implements BangumiSubject {
	    
	    private List<UserObserver> list;
	    private String  anime;
	    public Bangumi(String anime) {
	        this.anime = anime;
	    	list = new ArrayList<UserObserver>();
	    }
	    
	    @Override
	    public void toThem(UserObserver user) {
	        System.out.println("User"+user.getName()+"Subscribed"+anime+"!");
	        list.add(user);
	    }
	    
	    @Override
	    public void callOff(UserObserver user) {
	        if(! list.isEmpty()) System.out.println("User"+user.getName()+"Unsubscribe"+anime+"!");
	            list.remove(user);
	    }
	
	    @Override
	    public void notifyUser() {
	    	System.out.println(anime+"Updated! Start notifying subscribers of the show!"); list.forEach(user-> user.update(anime) ); }}Copy the code

Finally, a concrete observer is defined to implement the method of the abstract Observer interface.

The code is as follows:

	class  User implements UserObserver{
	private String name;
	public User(String name){
		this.name = name;
	}
	
	@Override
	public void update(String bangumi) {
		System.out.println(name+"Subscription to the show:" + bangumi+"Updated!");
	}

	@Override
	public String getName() {
		returnname; }}Copy the code

With that written, let’s test it. Here we define two user characters, Zhang SAN and Xuwujing, who have subscribed to Bing Tang and Fate/Zero. They will be notified when the dramas are updated. If they cancel their subscription to the show, he won’t be notified of it.

The corresponding test code is as follows:

	public static void main(String[] args) {
  		String name1 ="Zhang";
		String name2 ="xuwujing";
		String	bingguo = "Ice Guo";
		String	fate = "fate/zero"; BangumiSubject bs1 = new Bangumi(bingguo); BangumiSubject bs2 = new Bangumi(fate); UserObserver uo1 = new User(name1); UserObserver uo2 = new User(name2); // Subscribe to bs1.tothem (uo1); bs1.toThem(uo2); bs2.toThem(uo1); bs2.toThem(uo2); // notify bs1.notifyUser(); bs2.notifyUser(); // Unsubscribe bs1.calloff (uo1); bs2.callOff(uo2); // notify bs1.notifyUser(); bs2.notifyUser(); }Copy the code

Output result:

User Zhang SAN subscribed to Bing Tang! User Xuwujing subscribed to Bingguo! User Chang SAN subscribes to Fate/Zero! User Xuwujing subscribed to Fate/Zero! Bingguo has been updated! Start notifying subscribers of the show! Confectionery: Bingguo is updated! Xuwujing subscription drama: Bingguo update! Fate/Zero updated! Start notifying subscribers of the show! Fate/Zero update Fate/Zero Fate/Zero Users cancel their subscription to Confectioners! User xuwujing unsubscribe fate/ Zero! Bingguo has been updated! Start notifying subscribers of the show! Xuwujing subscription drama: Bingguo update! Fate/Zero updated! Start notifying subscribers of the show! Fate/Zero updateCopy the code

Advantages of observer mode:

Uncoupling makes both sides of the coupling dependent on abstraction so that neither transformation affects the transformation on the other side.

Disadvantages of observer mode

If an observed object has many direct and indirect observers, it can take a long time to notify all observers; If there is a circular dependency between the observer and the observing target, the observing target will trigger a circular call between them, possibly causing the system to crash. The observer mode has no corresponding mechanism to let the observer know how the observed object has changed, but only that the observed object has changed.

Usage Scenarios:

Scenarios that require associated behavior; Events need to create a scenario that triggers a chain, such as monitoring; Cross-system message exchange scenarios, such as message queues, event bus processing mechanisms.

Matters needing attention:

If the execution is sequential, an observer error will cause the system to stall. Asynchronous execution is recommended.

Empty object mode

Introduction to the

NullObject Pattern is mainly checked by replacing a NULL object instance with an empty object. Instead of checking for Null values, Null objects reflect a relationship that does nothing. Such Null objects can also provide default behavior when data is not available. The main purpose of this call is not to return Null, but to return an empty object, preventing Null pointer exceptions.

Empty object pattern, as a kind of design pattern which has been forgotten basically, but has the function that cannot be forgotten. The reason for this is that this pattern is almost impossible to see and use. It is not that it is not easy to use, nor is it used in a few scenarios, but it is more complicated to use than simple null value judgment. We can use the following example to illustrate why this is so. If we want to according to the user in the existing data to find relevant information, and information to return it back, so we are generally through the user name lookup in the database, and then the data coming back, but in the database to look up, probably not the user’s information, so returns Null, if slightly do not pay attention to, A null pointer exception occurs. We usually practice is at this moment, after query whether the data is Null, if it is Null, to inform the client without the data, although to do so may prevent the Null pointer exception, but too similar to the method, and returns the information entity for the same time, we need to decide, every time is a bit too complicated. Then we can use the empty object pattern to achieve this function.

First we define an abstract role with methods to get the name and determine whether it is null. The code for this abstract class is as follows:

interface AbstractUser {
   String getName();
   boolean isNull();
}
Copy the code

After defining the abstract class, we can define the concrete implementation class. Here we define two implementation classes, one represents a real user, returns a real name, one is a non-existent user, returns data in another way, can tell the client that the user does not exist, to prevent null Pointers. The code is as follows:

class RealUser implements AbstractUser {
   private String name;

   public RealUser(String name) {
   	this.name = name;
   }

   @Override
   public String getName() {
   	return name;
   }

   @Override
   public boolean isNull() {
   	return false;
   }
}

class NullUser implements AbstractUser {

   @Override
   public String getName() {
   	return "user is not exist";
   }

   @Override
   public boolean isNull() {
   	return true; }}Copy the code

We then define a factory role that provides an interface to the client to return query information. The code is as follows:

class UserFactory {

   public static final String[] names = { "zhangsan"."lisi"."xuwujing" };

   public static AbstractUser getUser(String name) {
   	for (int i = 0; i < names.length; i++) {
   		if (names[i].equalsIgnoreCase(name)) {
   			returnnew RealUser(name); }}returnnew NullUser(); }}Copy the code

Finally, the test code is as follows:


public static void main(String[] args) {
   	AbstractUser au1 = UserFactory.getUser("wangwu");
   	AbstractUser au2 = UserFactory.getUser("xuwujing");
   	System.out.println(au1.isNull());
   	System.out.println(au1.getName());
   	System.out.println(au2.isNull());
   	System.out.println(au2.getName());
}

Copy the code

Output result:

true
user is not exist
false
xuwujing

Copy the code

Advantages of empty objects:

It can strengthen the stability of the system and effectively prevent the impact of null pointer error on the whole system. Do not rely on the client to ensure the stability of the system;

Disadvantages of empty objects:

More code needs to be written to implement nullvalue judgment, which in some ways is not cost-effective;

Usage Scenarios:

When a large number of null values need to be judged;

other

Music to recommend

Share a rhythmic electric sound!

Project code

Java-study is some code that I have documented during my Java learning process, including the code used in previous posts. If the feeling is good, I hope to give a start, of course, if there is any deficiency, I also hope to propose. Github address: github.com/xuwujing/ja…

Original is not easy, if you feel good, I hope to give a recommendation! Your support is the biggest motivation for my writing! Copyright: www.cnblogs.com/xuwujing CSDN blog.csdn.net/qazwsxpcm Personal blog: www.panchengming.com