Declaring: Most of the code and some text in this series come from the network, copyright belongs to all of them.
13.Decorator
14.Facade
15.iterator
16.Observer
17.Template Method
13.Decorator Description: I started to see this mode, I saw a few times C # code description decoration mode, maybe I didn't skill, maybe it's too simple (not to understand code), I can't think of it. . Until the following Java example was turned over. This is a supplementary function of subclass (here assigning a child class), in C # is used in the interface implementation, in short, the subclass is achieved with the following method when it is not suitable. Function extension. I will not give it an example of C #, everyone carefully looks like this Java code should be more easily understood.
Example: Java programmers know that you can change the behavior of the class and extend a class by extending a class. This behavior is called inheritance, which is an important feature of object-oriented programming.
For example, if you want to get a Swing Type tab with a border, you can submit the javax.swing.jlabel class. However, subclass is not always effective. When the inherits can't solve the problem, you have to help with other ways. For example, use the Decorator mode.
This article explains what the Decorator mode is, and when it should be subclass, when you should use Decorate mode.
In the Java language, keywords Extends are provided with a class class (extension). Programmer with rich object-oriented programming experience knows the power of subclass. By expanding a class, we can change the behavior of this class. Take the JBorderLabel class that is told in Listing as an example, it extends the Javax.swing.jlabel class, except for a border, which has the same look and behavior as the JLabel class.
Listing 1 - The Jborderlabel Class, An Example of Subclassing
Package Decorator;
import java.awt.Graphics; import javax.swing.JLabel; import javax.swing.Icon; public class JBorderLabel extends JLabel {public JBorderLabel () {super ();} public JBorderLabel (String text) {super (text);} public JBorderLabel (Icon image) {super (image);} public JBorderLabel (String text, Icon image, int horizontalAlignment) {super (text, image, horizontalAlignment);} public JBorderLabel (String text, int horizontalAlignment) {super (text, horizontalAlignment);} protected void paintComponent (Graphics g) {super.paintComponent (g); int height = this.getHeight (); int width = this.getWidth (); g.drawRect (0, 0, width - 1, height - 1); }}
To understand how JBORDERLABEL work, we must first understand the principle of Swing painted its components. The Jlabel class is inherited to javax.swing.jcomponent.swing as other Swing components. They are viewed by calling the PAINT method of the JComponent component. We can modify the behavior of a component diagram interface by overloading the open method Paint of JComponent. Here is the definition of a Paint method for jComponent. Public void paint (graphicsg)
Objects that are passed as a PaINT method GRAPHICS is a drawing panel. To optimize the drawing, the PAINT method is divided into three methods with protection (Protected) properties: PaintComponent, PaintBorder, Paintchildren. Paint method calls these three methods to pass it to these three methods at the same time. Below is a statement of these three functions:
Protected Void PaintComponent (Graphics G) Protected Void PaintBorder (Graphics G) Protected Void PaintChildren (Graphics G)
You can customize your own way of drawing components by overloading these methods.
The JBORDERLABEL class overloads the PaintComponent method for javax.swing.jcomponent. The PaintComponent method of class JBORDERLABEL first calls the parent class's PaintComponent to get a JLabel. It maintains its own length and wide, draw a rectangle through the DrawRect method of the Java.awt.Graphics instance. An instance of the JBORDERLABEL class is the same as the JLabel look except a border.
This example is quite good in neutrophily. Let's take a look at the case of subclassification. If you plan to make other components have the same behavior (such as: draw a border), then you have to do a lot of subclassics. In the list 1, subcatenation looks very simple because you only need to overload a method in an example. When you have too many subclasses that need to be created, your code will become very complicated, and the opportunity to make an error increase. (You must copy (Reproduce) your subclasses need to support the parent class constructor, just like the JBorderlabel class). At this time, the best way is to use the Decorator mode.
Decorator mode
In the "Design Patterns: Elements of Reusable Object-Oriented Software" written in Erich Gamma, Decorator mode is classified as structure mode. Decorator mode provides an alternative to subclass. The main difference between subclass and Decorator model is: use subclasses, and you can deal with the same class; use Decorator mode, you can dynamically modify multiple objects. When you expand (Extend), your changes to the son class will affect all instances of this son class. With Decorator mode, what you do will only affect the object you intend to change.
Understanding the JComponent class is important for writing decorations, we pass this decorator class to change the user interface of the Swing component. In front part I explain how JComponent draws its user interface, we can find all members of this class through documentation. We have to realize that the JComponent has a child, and these subcomponents will also draw when JComponent is drawn.
Create a Swing decoration that extends from JComponent. This decorator's constructor accepts a parameter of a type JComponent. You can pass any one of the SWING objects that need to change behavior to the decoration. This decorator will pass this component as its own subcomponent. It is not to add Swing components to JFRAME or JPANNEL or other containers, but then add SWING components to the modifier, and add the modem to the container class. Because a modem is also an object of a JComponent type, the container cannot distinguish them. This decoration is a subcomponent of this container. This decoration will be called when the container is retransmonded by the decorator. For example, suppose you have a JLabel class, you intend to pass it to a JFrame class called Frame1. Use the following code:
Frame.getContentpane (). Add ("a label"));
Use myDecorator to modify the JLabel code and it is very similar, as follows: (Remember, the constructor of the MyDecorator class should accept an input parameter of a JComponent class)
Frame.getContentPane (). Add (New MyDecorator (New Jlabel ("a label"))
This article example has an example of two Decorator modes. The first example is BorderDecorator. This class is used to modify the JComponent so that JComponent has a border. When a JLabel modified by BorderDecorator is added to JFrame, this Jlabel looks like an instance of JBorderLabel. This shows that subcatenation is not necessary. Better, you can pass any Swing component to BorderDecorator, which is passed to give a border. In this example, the behavior of different types of instances is changed by creating a class BorderDecorator.
The second example is ResizableDecorator. This decoration adds a small button to the upper left corner for each Swing component passed to it. When the user clicks this button, this component will minimize this button.
BorderDecorator class
We start with BorderDecorator. The decorator of this class will add a border for the SWING component. Sample code as list 2
Listing 2 - The BorderDecorator Class
package decorator; import javax.swing.JComponent; import java.awt.Graphics; import java.awt.Color; import java.awt.BorderLayout; public class BorderDecorator extends JComponent {// decorated component protected JComponent child;
Public BorderDecorator (JComponent Component) {child = Component; this.setLayout (New BorderLayout ()); this.add (child);}
Public void Paint (Graphics G) {Super.Paint (g); int Height = this.getHEight (); int width = this.getwidth (); g.drawRect (0, 0, width - 1, height - 1); }} Note that this BorderDecorator extends JComponent, and its constructor accepts a parameter of a JComponet type. This BorderDecorator class has a type of property Child, which is a reference to the JComponent object.
14.Facade Description: Facade is the meaning of facade, as the name implies, providing a consistent interface for a set of interfaces in the subsystem. This mode is in use, for a few more, if there is a 100-line code, contain 5 functions, you will naturally write it into 5 functions, then arrange their logical relationship with a master. The parameter list of each function is an interface. You don't have to care about its internal processes when you use the function, just care about the interface. The same Java example, the following Java examples, using the database operations that are familiar with themselves. Example: Facade A typical application is the application of database JDBC, as follows of the following example: public class dbcompare {connection conn = null; preparedStatement preip = null; resultSet Rset = null; try {class.forname ("<; driver>; ") .Newinstance (); conn = drivermanager.getConnection (" <; data>; "); string sql =" select * from <; table>; where <; colorn name>; =? "; Preip = conn.preparestatement (SQL); Prep.setString (1, "<; color"; "); RSET = preP.executeQuery (); if (Rset.Next ()) {system.out.println (RSET.GETSTRING (" <; Column name ");}} catch (sexception e) {E.PrintStackTrace ();} finally {rset.close (); prep.close (); conn.close ();}} Above the most common in JSP For database operational measures. In the application, it is often necessary to operate the database, and each time you write the above code will definitely be more troublesome. You need to extract some of the unscrupulous parts, make an interface, which introduces the Facade look.
If we replace <; driver> in class.Forname later, it is also very convenient, such as replacing the Oracle database from the MySQL database, as long as the Driver in the Facade interface can be replaced. We made a FACADE interface, using this interface, the program in the previous example can be changed as follows: public class dbcompare {string sql = "select * from <; table>; WHERE <; colorn name>; =?"; TRY {Mysql msql = new mysql (SQL); prep.setString (1, "<; color"; "); RSET = prep.executeQuery (); if (Rset.Next ()) {System.out.println (Rsett) .getstring ("<; column name");}}} catch (sexception e) {E.PrintStackTrace ();} finally {mysql.close (); mysql = null;}} is very simple, all programs are accessible to database They are all uses this interface, reducing the complexity of the system, increasing flexibility. If we want to use the connection pool, you can modify the FACADE interface. As can be seen from the figure, FACADE is actually a common way to reduce system relationships, reducing a common method of inter-system coupling, maybe you are not known, although I don't know it is facade.
15.Iiterator Description: This is the easiest mode using the easiest mode because it has been integrated into the collection class of the class library in Java or C #, in Java, this mode has been integrated into the collection of Java. Most of most There is no need to create an Iterator yourself, just load the object into the Collection, use Iterator to traverse. On C # As long as IENUMERABLE is implemented and the Ienumerator interface. It is also very simple to achieve, as follows: Class List: ienumerable {private t [] Elements; public ienumerator getenumerator () {foreach (t element (t element "} {yield element;}}}
16.observer Description: I can't help but smile, is it easy to make people think that Windows's message mechanism is, and the Windows message is responsible for distributing by the system's Message Station. I think it is always difficult to Windows message mode when I exchange information between multiple objects, causing a Windows message distribution program that is very difficult, (not just with a thread list, the object is between The parameters and thread objects will bring problems), although it is natural to think of this model, but always think is very trouble, so there is no deep thinking, now I see the following example, I feel that I have to construct a message distributor It is easy to easily, the parameter transmission is easy, the only unique is not versatility (wants to have a versatility estimate to increase the support to the class library). This model is made very convenient to implement this mode with C #'s delegate. 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.
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.
Example: When writing multi-storey applications, we usually separate the representation layer and data logic layers, such as a very common view / document structure, the result of this designed approach is usually a single view simultaneously Data sources, such as a web site, easy to 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 Realization We first 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.
// class Subject {// implementation code because they do not know how many viewers, so the establishment of an observer 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 (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 {// the object contains a protected Subject s need to observe; public Subject ObservedSubject {get {return s;} set {s = value;}} abstract public void Update ();} ConcreteSubject (target entities, where considerable Data logic layer): Deposit the status into each ConcReteSubject object. When it changes, it is a notification to each of its observes. // There is basically nothing here, and 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 () {// out of the display data Console.WriteLine ( "In Observer {0}: data from subject = { 1} ", observername, simportantsubjectdata;}}
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;}}
The advantage of the mode analysis 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 can be a variety of different representations (observations) By). 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. Observer pattern to achieve improved define a Delegate: delegate void UpdateDelegate (string SubjectData); Subject (abstract goal): class Subject {private string strImportantSubjectData = "Initial"; // define an event container, instead of the observer in front of the object list public event UpdateDelegate UpdateHandle; public string ImportantSubjectData {get {return strImportantSubjectData;} set {strImportantSubjectData = value;}} public void Notify () {// event is issued 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: // In order to be more clear, two entity observer is defined here, note that there is no relationship between them Class Observer1 {Private String ObserverName; Public Observer1 (String Name) {ObserverName = name;} public void Update1 (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);}} The main function: public class Client { Public static int main (string [] args) {concreteSubject (); observer1 o1 = new observer1 ("first observer"); Observer2 O2 = New Observer2 ("SECOND OBSERVER"); // Register object to the target An observer, please note that only two methods are added here, // Don't need to care about how to come, and don't need to care about how the target class will call them. S.UpdateHandle = new updatedeLegate (o1.Update1); s.UpdateHandle = new updatedlegate (o2.Update2); simportantsubjectData = "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 #.
Complete source code is the complete source code: namespace Observer_DesignPattern {using System; delegate void UpdateDelegate (string SubjectData); class Subject {private string strImportantSubjectData = "Initial"; public event UpdateDelegate 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 Update1 (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;}}} 16.Template Method Description: Define the skeleton of an action algorithm to delay some steps to its subclass. Very simple Everyone looks at the example below!
Example: When using Java abstract classes, Template mode is often used, so the template mode is commonly used. And it is easy to understand and use. Public Abstract Class Benchmark {/ ** * The following is we hope to complete * / public abstract void benchmark (); / ** * Repeat Benchmark * / public final long repeat (int count) {ix <= 0) RETURN 0; Else {long starttime = system.currenttimemillis (); for (int i = 0; i Long stoptime = system.currenttimemillis (); return stoptime - starttime;}}} In the above example, we want to repeat the Benchmark () operation, but there is no description of the specific content of Benchmark (), but is delayed into its subclass: Public class method {/ ** * Really defined Benchmark content * / public void benchmark () { For (int i = 0; I At this point, the Template mode has been completed, is it simple? We call the REPEAT method as a template method, which is implemented in the subclass MethodBenchmark, which is delayed. See how to use: Benchmark Operation = new methodbenchmark (); long duration = Operation.repeat (Integer.Parseint (args [0] .trim ())); System.out.Println ("The Operation TOOK" Duration "MilliseConds"); Maybe you have used what is the use of abstract classes, now you should completely understand it? As for the benefits of this, it is obvious, the extension is strong, and the Benchmark content changes, I will do it again, don't have to be Modify other application code.