Observer mode is a model we have applied because it defines the message delivery of a single data source multi-view structure and object design, so almost all of the multi-layer applications that will represent layers and data logic layers. It can use the OBServer mode. This article will analyze the C # language to implement the code of this mode, and some shortcomings exist for this mode, using C #'s new feature delegate to try some improvements to this mode.
In order to let more people can understand this article, before this, let's first understand the basic concept of the OBServer mode.
Mode Name: OBServer
Structural map:
intention:
Define a pair of dependencies between objects, when the status of an object changes, all objects that depend on its object are notified and automatically updated.
applicability:
One aspects are dependent on the other aspect. The two are encapsulated in separate objects to make them independently change and reuse.
When changes to an object requires simultaneous changes, don't know how many objects have to be changed.
When an object must notify other objects, it can't assume who other objects are. In other words, you don't want these objects to be closely coupled.
Application: When writing multi-storey applications, we usually separate the representation layers and data logic layers, such as a very common view / document structure, the result of this design method is usually used in the same manner. Single data sources, such as a web site, you can easily have an HTML page for your computer and a WAP page for your phone. When using this structure, in order to maintain the consistency of the data display, the data source must be required to inform each of the representations of each one and its binding representation when data changes. But the problem is that the data layer itself does not know how many different representations in the end reflect its data content. Therefore, it is necessary to design a set of effective mechanisms to complete this goal.
Pattern Implementation: Let's see the conventional C # implementation code from the "Design Mode Mini Manual".
Subject (Abstract Objective): The target knows its observer. There can be any other observer to observe the same goal.
// Implement code
Class Subject {// Because I don't know how many observes, I created an observer link list private arraylist list = new arraylist (); private string strimportantsubjectData = "initial";
Public String ImportantsUbjectData {Get {Return StrimportantsUbjectData;} set {strimportantsubjectData = value;}}
Public void attach (observer o) {list.add (o); o.observedsubject = this;}
Public void detach (Observer O) {}
Public void notify () {// After the data changes, the traversal list notifies the observer Foreach (OBServer O IN List) {o.Update ();}}}
Observer: Defines an update interface for objects that need notifications when changing at the target.
Abstract Class Observer {// Built-in A Object Protected Subject S; Public Subject ObservedSubject {Get {Return S;} Set {S = Value;}}} Abstract Public Void Update ()
ConcreteSubject (entity target, is equivalent to the data logic layer): deposit the relevant state into each contrateSubject object. When it changes, it is a notification to each of its observes. // Basically, there is basically nothing, the data can be placed in getState () Class ConcreteSubject: Subject {public void getState () {
}
Public void setState () {
}
ConcreteobServer (entity observer is equivalent to the representation): Maintain a reference to ConcreteSubject. Save the status, these states should be consistent with the status of the target. Implement the OBServer update interface to keep your own state with the target status.
Class ConcreteObserver: Observer {Private String ObserverName;
Public concreteobserver (string name) {ObserverName = name;}
Override public void update () {/ Display data is displayed in Console.Writeline ("IN Observer {0}: Data from Subject = {1}", OBServerName, S.ImportantsUbjectData);}}
Main function:
Public class client {public static int main (string [] args) {
ConcreteSubject s = new concreteSubject (); concreteobserver O1 = New ConcreteobServer ("first observer"); concreteobserver o2 = new concreteobserver ("SECOND OBSERVER");
// Registered the observer S.attach (O1); s.attach (O2); s. ImportantsubjectData = "this is important subject data"; s.Notify (); return 0;}}
Mode Analysis: The advantage of the OBServer mode is to achieve separation of the layer and the data logic layer, and define a stable update message transfer mechanism, the category is clear, and the update interface is abstracted, so that there are a variety of different representations ( Observer). However, its disadvantage is that each appearance object must inherit this abstraction interface class, which has caused some inconvenience, such as an exterior object written by others, does not inherit the abstract class, or the interface is wrong, we hope not Modify this class directly using it. Although Adapter mode can be applied to some extent, this problem is solved, but it will cause more complex and artistic design to increase the error rate. C # As an advanced modern object-oriented language, not only the essence of many languages, but also creates some very useful new features. After learning the C # language, I found that using C # unique delegate can come to better solve this problem.
Improved OBServer mode implementation:
First define a delegate: delegate void UpdatedLegate (String SubjectData);
Subject (abstract target):
Class Subject {
private string strImportantSubjectData = "Initial"; // define an event container, instead of the list of objects in front of the observer public event UpdateDelegate UpdateHandle; public string ImportantSubjectData {get {return strImportantSubjectData;} set {strImportantSubjectData = value;}}
Public void notify () {// Event IF (UpdateHandle! = NULL) UpdateHandle (StrimportantSubjectData);}}
Observer: None, because there is no need to abstract interface classes, you can save the abstract observer class.
ConcreteSubject: // No change Class ConcreteSubject: Subject {public void getState () {
}
Public void setState () {
}
ConcreteobServer (entity observer):
/ / In order to be more clear, two entity observes are defined here, note that there is no relationship between them Class Observer1 {Private String ObserverName;
Public Observer1 (String Name) {OBServerName = Name;}
Public void update11 (String ImportantSubjectData) {Console.WriteLine ("IN Observer {0}: Data from Subject = {1}", ObserverName, ImportantSubjectData);}}
Class Observer2 {Private String ObserverName;
Public Observer2 (String Name) {ObserverName = Name;}
Public void update2 (String ImportantsubjectData) {Console.Writeline ("IN Observer {0}: Data from Subject = {1}", ObserverName, ImportantsUbjectData);}}
Main function:
public class Client {public static int Main (string [] args) {ConcreteSubject s = new ConcreteSubject (); Observer1 o1 = new Observer1 ( "first observer"); Observer2 o2 = new Observer2 ( "second observer");
// Two observers to the target registration object, please note that only two methods are added, and do not need to care about how to come from, and do not need to care about how to call them. S.UpdateHandle = new updatedLegate (O1.Update1); s.UpdateHandle = new updatedLegate (o2.Update2);
S.ImportantsUbjectData = "this is important subject data";
S.Notify (); return 0;}}}
In this code, did not see the list, did not see the traversal operation, did not see how the update was called, and even didn't see the abstraction class and abstract interfaces of classes that were contacted together, but the target object Can send data update information to each observer object, and more easily add new different observer objects, do not need to know where it is inherited, nor does it need to unify their interface call. . All this is attributed to the flexible powerful C #. The following is a complete source code:
Namespace observer_designpattern {using system;
Delegate Void UpdatedLate (String SubjectData);
Class Subject {
PRIVATE STRING STRIMPORTANTSUBJECTDATA = "Initial";
Public Event UpdatedLegate UpdateHandle;
Public String ImportantsUbjectData {Get {Return StrimportantsUbjectData;} set {strimportantsubjectData = value;}}
Public void notify () {if (updateHandle! = null) UpdateHandle (StrimportantsUbjectData);}}
Class ConcreteSubject: Subject {public void getState () {
}
Public void setState () {
}
Class Observer1 {Private String ObserverName;
Public Observer1 (String Name) {OBServerName = Name;}
Public void update11 (String ImportantSubjectData) {Console.WriteLine ("IN Observer {0}: Data from Subject = {1}", ObserverName, ImportantSubjectData);}}
Class Observer2 {Private String ObserverName;
Public Observer2 (String Name) {ObserverName = Name;}
Public void update2 (String ImportantsubjectData) {Console.Writeline ("IN Observer {0}: Data from Subject = {1}", ObserverName, ImportantsUbjectData);}}
public class Client {public static int Main (string [] args) {ConcreteSubject s = new ConcreteSubject (); Observer1 o1 = new Observer1 ( "first observer"); Observer2 o2 = new Observer2 ( "second observer");
S.UpdateHandle = new updatedLegate (O1.Update1); s.UpdateHandle = new updatedLegate (o2.Update2);
S.ImportantsUbjectData = "this is important subject data";
S.Notify (); return 0;}}}