Subscription publishing mode (Subscribe/publish)

Source: Internet
Author: User

The subscription publishing mode defines a One-to-many dependency that allows multiple subscriber objects to listen to one subject object at the same time. This subject object notifies all subscriber objects when their state changes, enabling them to automatically update their state.

One of the bad side effects of splitting a system into a series of interacting classes is the need to maintain consistency among the objects, which can be inconvenient for maintenance, extension, and reuse. Subscription publishing mode is used when changes to an object need to change other objects at the same time, and it does not know how many objects need to be changed.

An abstract model has two aspects, one of which relies on the other, when the subscription publishing model can encapsulate the two in separate objects, allowing them to change and reuse independently. The way the subscription publishing mode works is to decouple. Let both sides of the coupling rely on abstraction, not on the concrete, so that the individual changes do not affect the other side of the change.

When we write programs on a daily basis, we often experience the following situations:

public void has alarm information generated ()
{
Refresh interface ();
Update database ();
Send mail to admin ();
....................................
}

When the alarm information is generated, the following steps should be performed: Refresh the interface (), update the database (), send mail to the administrator () and so on. On the surface to see the code is very neat, in fact, there are many problems: first of all, this is a process-oriented development, is not suitable for large-scale projects. Second, the amount of code maintenance is too large. Imagine, if there are more than 10 actions to be performed after the alarm is generated, what a large and complex class it will be, a long time, perhaps even the developers themselves do not know how to maintain. Third, poor scalability. If the alarm is generated, to add a voice prompts () function, how to do it. Yes, it can only be added to the function that has the alarm information generated (), which violates the "open-close principle". And it modifies the original function, then in the test, in addition to testing the new features, but also to do the original function of regression test; In a large project, it may take about two weeks to do a regression test, provided that the new features do not affect the original functionality and create new bugs.

So how do I get the alarm information () function to be decoupled from other functions? Don't worry, here is the lead----subscription publishing mode. See figure below:

The above process is a description of the function that has the alarm information generated (). What we're going to do is decouple the alarms from the events that they need to be notified, so that there is no dependency between them, and the solution coupling diagram is as follows:

The event trigger is abstracted, called the message publisher, which is p in the graph. Event acceptance is abstracted, called the message Subscriber, which is the s in the diagram. P and S are connected by S.P (that is, the subscriber). Thus, the decoupling of P and S is realized. First, p sends the message to the specified subscriber, and from the beginning to the end, it doesn't know or care about which s to send the message to. s if you want to receive messages, you have to subscribe to the Subscriber, after the successful subscription, s can receive messages from the S.P, from the beginning to the end, s do not know or care about the source of the specific p. In the same way, S can also unsubscribe to S.P, after the successful unsubscribe, S can not receive the message from the specified S.P. This solves the problem of decoupling between P and s perfectly.

Wait, there seems to be another problem. From the diagram, although the P and S to complete the understanding of decoupling, but P and S.p,s and S.P between the coupling. In fact, this problem is a good solution, think of our last chapter of the decoration mode is how to decouple. Yes, on the interface. Here we also use interfaces to solve the decoupling between P and S.P and S and S.P, while using delegate to solve multiple subscription multiple-release mechanisms.

The implementation code is given below. Because the subscription publishing mode involves P, S.P and S three parts, the code is more and longer. Please read it patiently.

First, to achieve decoupling between P and S.P, S and S.P, we need to define two interface files

ISubscribe.cs
Namespace TJVictor.DesignPattern.SubscribePublish
{
Defining subscription Events
public delegate void Subscribehandle (String str);
Defining a subscription interface
public interface iSUBSCRiBE
{
Event Subscribehandle Subscribeevent;
}
}

Ipublish
Namespace TJVictor.DesignPattern.SubscribePublish
{
Defining Publishing Events
public delegate void Publishhandle (String str);
Defining the Publishing interface
public interface Ipublish
{
Event Publishhandle Publishevent;

void Notify (String str);
}
}

Then we'll design the Subscriber. Obviously the subscriber to achieve two-way decoupling, it is necessary to inherit the above two interfaces, which is why I use the interface without the abstract class reason (class is a single inheritance).

Namespace TJVictor.DesignPattern.SubscribePublish
{
    public class Subpubcomponet: iSUBSCRiBE, Ipublish
    {
        private string _subname;
        public subpubcomponet (string subname)
         {
            this._subname = subname ;
            publishevent + + new Publishhandle (Notify);
       }

#region iSUBSCRiBE Members
Event Subscribehandle Subscribeevent;
Event Subscribehandle Isubscribe.subscribeevent
{
Add {subscribeevent + = value;}
Remove {subscribeevent = value;}
}
#endregion

#region Ipublish Members
Public Publishhandle publishevent;

Event Publishhandle Ipublish.publishevent
{
Add {publishevent + = value;}
Remove {publishevent = value;}
}
#endregion

public void Notify (String str)
{
if (subscribeevent!= null)
Subscribeevent.invoke (String. Format ("message source {0}: Message content: {1}", _subname, str));
}
}
}

The next step is to design subscriber S. The S class uses iSUBSCRiBE to decouple from the S.P. The code is as follows:

Namespace TJVictor.DesignPattern.SubscribePublish
{
public class Subscriber
{
private string _subscribername;

Public Subscriber (String subscribername)
{
This._subscribername = Subscribername;
}

Public iSUBSCRiBE Addsubscribe {set {value. Subscribeevent + = Show; } }
Public iSUBSCRiBE Removesubscribe {set {value. Subscribeevent-= Show; } }

private void Show (String str)
{
Console.WriteLine (String. Format ("I am {0}, I receive a subscription message is: {1}", _subscribername, str));
}
}
}

The last is the publisher P, which inherits Ipublish to notify S.P of the announcement.

Namespace TJVictor.DesignPattern.SubscribePublish
{
public class Publisher:ipublish
{
private string _publishername;

Public Publisher (String publishername)
{
This._publishername = PublisherName;
}

Private event Publishhandle Publishevent;
Event Publishhandle Ipublish.publishevent
{
Add {publishevent + = value;}
Remove {publishevent = value;}
}

public void Notify (String str)
{
if (publishevent!= null)
Publishevent.invoke (String. Format ("I am {0}, I publish {1} message", _publishername, str));
}
}
}

At this point, a simple subscription publishing model has been completed. Here is the calling code and the running result. The calling code simulates the subscription publishing relationship in Figure 2, which you can see from the code, the run results, and the example diagram.

#region TJVictor.DesignPattern.SubscribePublish
Create a new two subscriber
Subpubcomponet SubPubComponet1 = new Subpubcomponet ("Subscriber 1");
Subpubcomponet SubPubComponet2 = new Subpubcomponet ("Subscriber 2");
Create a new two publisher
Ipublish publisher1 = new Publisher ("TJVictor1");
Ipublish publisher2 = new Publisher ("TJVictor2");
Associating with Subscribers
Publisher1. Publishevent + = subpubcomponet1.publishevent;
Publisher1. Publishevent + = subpubcomponet2.publishevent;
Publisher2. Publishevent + = subpubcomponet2.publishevent;
Create a new two subscriber
Subscriber S1 = new Subscriber ("Subscriber 1");
Subscriber S2 = new Subscriber ("Subscriber 2");
To subscribe
S1. Addsubscribe = SubPubComponet1;
S1. Addsubscribe = SubPubComponet2;
S2. Addsubscribe = SubPubComponet2;
Publisher Post Message
Publisher1. Notify ("blog 1");
Publisher2. Notify ("blog 2");
Send End Symbol
Console.WriteLine ("". PadRight (50, '-'));
S1 Unsubscribe to Subscriber 2
S1. Removesubscribe = SubPubComponet2;
Publisher Post Message
Publisher1. Notify ("blog 1");
Publisher2. Notify ("blog 2");
Send End Symbol
Console.WriteLine ("". PadRight (50, '-'));
#endregion

#region Console.ReadLine ();
Console.ReadLine ();
#endregion

Run the result diagram:

Open Source Component: http://www.cnblogs.com/aarond/p/PubSub.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.