Subscription publishing mode

Keywords: Unity3d

Subscription publishing mode

The subscription publication pattern defines a one to many dependency, allowing multiple subscriber objects to listen to a topic object at the same time. When the subject object changes its state, it will notify all subscriber objects so that they can automatically update their state.

   Dividing a system into a series of cooperative classes has a very bad side effect, that is, the consistency between corresponding objects needs to be maintained, which will bring inconvenience to maintenance, extension and reuse. When the change of an object needs to change other objects at the same time, and it does not know how many objects need to be changed, it can use the subscription and publication mode.

   An abstract model has two aspects, one of which depends on the other. At this time, the subscription and publication mode can encapsulate the two in independent objects to make them change and reuse independently. The work of subscription publication mode is actually decoupling. Let both sides of the coupling rely on abstraction rather than concrete, so that their changes will not affect the changes on the other side.

The event trigger is abstracted and called the message publisher, that is, P in the figure. Event acceptors are abstracted and called message subscribers, that is, s in the figure. P and s are connected through S.P (i.e. subscriber). In this way, the decoupling of P and S is realized. First, P sends the message to the specified subscriber. From beginning to end, it does not know or care which s to send the message to. If s wants to receive messages, it needs to subscribe to the subscriber. After the subscription is successful, s can receive messages from S.P. from beginning to end, s does not know or care about the specific P from which the message comes. Similarly, s can unsubscribe from S.P. after unsubscribing successfully, s cannot receive the message from the specified S.P. This perfectly solves the decoupling between P and s.

Although P and s are decoupled, aren't P and S.P, s and S.P coupled again? In fact, this problem is easy to solve. Think about how the decoration mode in the previous article is decoupled? Yes, just the interface. Here, we also use interfaces to solve the decoupling between P and S.P and between S and S.P. at the same time, we use delegate to solve the mechanism of multi subscription and multi publication.

The implementation code is given below. Because the subscription and publication mode involves three parts: P, S.P and s, there are many codes and are relatively long. Please read it patiently.

Firstly, in order to realize the decoupling between P and S.P, and between S and S.P, we need to define two interface files

ISubscribe.cs
namespace TJVictor.DesignPattern.SubscribePublish
{
    //Define subscription events
    public delegate void SubscribeHandle(string str);
    //Define subscription interface
    public interface ISubscribe
    {
        event SubscribeHandle SubscribeEvent;
    }
}

IPublish
namespace TJVictor.DesignPattern.SubscribePublish
{
    //Define publishing events
    public delegate void PublishHandle(string str);
    //Define publishing interface
    public interface IPublish
    {
        event PublishHandle PublishEvent;

        void Notify(string str);
    }
}

Then we design the subscriber. Obviously, to realize bidirectional decoupling, subscribers must inherit the above two interfaces, which is why I use interfaces instead of abstract classes (classes are 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("Source{0}:Message content:{1}", _subName, str));
        }
    }
}

Next is design subscriber s. ISubscribe is used in s class to decouple from 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},The message I received from the subscription is:{1}", _subscriberName, str));
        }
    }
}

Finally, publisher P inherits ippublish to publish message notifications to S.P.

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 release{1}news", _publisherName, str));
        }
    }
}

So far, a simple subscription and publication mode has been completed.

Posted by wolfraider on Sun, 05 Dec 2021 09:02:28 -0800