One: Background: Decorator * Decorator is often translated into "decoration", I think it is more imageable to "painter", the painter (Decorator) is used to brush paint, then the paint object we call Decoratee. This Two entities are required in Decorator mode.
* Decorator definition: Dynamically add some additional responsibilities to an object, just brush paint on the wall. It is more flexible to use the Decorator mode to achieve a function with a generated subclass.
* Why use Decorator? We can usually use inheritance to implement the development, if these needs have a wide variety of features, it is bound to generate a lot of subclasses, increase the complexity of the system, and use inheritance implementation function to expand, we must These expansion functions are foreseen, which is determined when compiling is static. The reason for using Decorator is that these features need to be added by the user to the way. Decorator provides "Plug and Plan" method, How to increase when it is decided during operation.
* For this mode, it is initially summarized as 1. The basic function is the interface 2. Decorator parameter is also the interface itself to the next Decorator parameter 3. The basic function class implements the interface and as the parameter of the Decorator constructor, so that in this basis Add new features to add 4. Additional functions are processed by data structures in Decorator
Two: Question: This is an implementation example of a Decorator design pattern.
Basic features: The function of the Counter needs to be added 1: Ultimate Control 2: Lower Control
Import java.io. *; coplass counter {private int value; public counter (int V) {system.out.println ("init me here in the counter"; value = v;} public counter (Counter CC) PUBLIC Counter ) {System.out.println ("init me here in the counter"; value = cc.value;} public int} ("Read Me Here the value is:" @ r in ou ou p i Value); System.out.Println ("Read Me Here in the counter!"); return value;} public void increment () {System.out.println ("Increment Me Here in the counter!"); value ;} Public void Decrement () {system.out.println ("Decrement Me Here in the counter!"); value--;}}
Class Decorator Extends Counter {Counter Counter; Public Decorator (Counter C) {Super (C); System.out.Println ("Init Me Here with Class Decorator!");}}
Class UpperLimit Extends Decorator / / Upper Limit Control {Public UpperLimit (Counter C) {Super (C); Counter = C; System.out.Println ("Init Me Here with Class Upperlimit!");} public void increment () {
IF (counter ");" Too High ");} else {system.out.println (" Increment Me Here with Class Upperlimit!); Counter.Increment (); } / * Public void Decrement () {counter.Decrement ();} public int} () {Return counter.read_value ();} * /}
Class LowerLimit Extends Decorator // Lower Limit Control {Public LowerLimit (Counter C) {Super (C); Counter = C; System.out.Println ("Init Me Here In The Counter with Class Lowerlimit!");} public void Decrement ) {System.out.println ("Class Value:" Read_Value ()); System.out.println ("Dec value:" counter.read_value ()); if (counter.Read_Value () <= 0) { System.out.println; System.out.Println ("TOO Low");} else {system.out.println ("Decrement Me Here In The Counter with Class Lowerlimit!"); Counter. Decrement ();}} / * public void increment () {counter increment ();} public int} () {return counter.read_value ();} * /}
Class CounterFactory {public static counter CreateCounter (int value, int su) {copy (op) {casse 1: {return new counter (value);} case 2: {return new upperlimit (new counter);} case 3 : {Return New LowerLimit (New Counter (Value)); DEFAULT: {Return New UpperLimit (New LowerLimit (New Count (Value));}}}
} Class Console {private static BufferedReader read = new BufferedReader (new InputStreamReader (System.in)); public static int readInt (String index) {System.out.println (index); try {return Integer.parseInt (read.readLine ( )));} CatCH (Exception E) {RETURN 0;}}}}
Public class Q1S {public static void main (string [] args) {system.out.println ("counter type:"); system.out.println ("1: Normal"); system.out.println ("2: Upper limited "); System.out.println (" 3: Limit "); System.out.Println (" 4: Upper & Lower Limit "); int option = console.readint (" Enter Choice: "); Counter C = counterterfactory.createcounter (6, option); int choice = 1; while (choice! = 4) {system.out.println ("1: increment"); system.out.println ("2: Decrement"); System.out.println ("3: Read value"); System.out.println ("4: exit"); choice = console.readint ("Enter Choice:"); switch (choice) {case 1: C. Increment (); break; cas 2: c.Decrement (); break; case 3: int v = c.read_value (); system.out.println ("value =" v); break;}}}} The following steps are obvious as follows: 1: Select 3, "Lower Limit", 2: Select 3, "Read value" is 63: Select 1, "Increment" (Since then the value value should be 7) 4: Select 3 The value obtained by "read value" is 7 (correct) 5: Select 2, "Decrement" (this LaRue value should be 6) 6: Select 3, "Read value" value is 7 (the problem appeared) investigation This problem also occurs when Upper Limit
Three: Investigate the tracking statement from the output can see the start two output statements in the Class LowerLimit's Decrement method with significant guiding significance and one of them is called read_value () and the other for the polymeric object read_Value. ). The sixth step in the above steps is output to the Class value: 7 DEC VALUE: 6, there are two values existence. How is the problem? Continue to observe, the factory calls the Return New LowerLimit (New Counter (Value)) when the STR is selected; the new anonymous object is the parameter, continue to track the process, discover the anonymous object in the Class Decorator Point to before pointing, Decorator also passes the anonymous object to its parent class, while the parent class gets only the copy of the value in the object, thereby there are two Value exist: 1. In Decorator itself ( Value of the parent class 2. Also in Decorator itself (Value attribute of member variable counter)! The problem gradually, observed Class LowerLimit again, which only implemented the Decrement () method, that is, when the LowerLimit calls read_value () and increment (), it is traced back to its parent class, and the value of the value VALUE For the first type. When calling the DECREMENT () method for the LowerLimit, the method is performed with its member variable counter (). The value that is active is a second type of value. So there is a phenomenon that the value value is not synchronized. Four: Solution is obvious, the solution is to use only one of the value values, of course, the purpose of the Decorator itself is to avoid inheritance, so the original method should be covered by means of member variables. Implementation. That is to remove the comments in the code.
5: Small knot parent class gets only a copy of the value and the aggregate object of itself obtains all the references (parameters), if there is no way to overwrite the original, the method will operate along the value of the parent class (Value) The way to be covered will operate the value (value) in the object of the polymerization of the proportion to the value of the two value values to generate differences from the Decorator mode itself. I can know: Add (not using the dynamic function on the existing class Inheritance is achieved, in order to prevent too deep, it is difficult to control), so the parameters of the constructor should also be treated as a "existing class foundation", that is, their aggregate object must be referenced by this parameter, all methods It must also be reused, otherwise it will fall into the inheritance trap.
Six: Do you have a copy of Value in your pupil? What is its role? Side Effect?