Objective
Learning design patterns has been around for some time, the previous period of time has been busy an Android app, no time to update. Today is a bit empty, in the spirit of open source, the strategic model of some things to share.
Note: Bo Master is only a junior student who is engaged in Android, the following is purely self-taught, if there is an incorrect place to welcome the point.
Body
Reprint Please specify source: http://blog.csdn.net/h28496/article/details/46403815
Release Date: June 7, 2015
Author's information: Central Peking University School of Zhenghaipeng
Explain why you should have a policy model
Suppose a scenario: we have some sort algorithms, and we need to look at the ordering process for each sorting algorithm. It is then encapsulated as a client.
1. What should be done under normal circumstances?
We can write a client class Client_notusestrategy.java, as follows: (note the switch-case inside the Run () method)
/** * Client not using policy mode * @author Zhenghaipeng */public class Client_notusestrategy {public static final int insert_sort = 0;public stat IC final int bubble_sort = 1;int sorttype;int[] a;public client_notusestrategy (int sorttype, int[] a) {This.sorttype = Sor TTYPE;THIS.A = A;} public void Run () {switch (sorttype) {case insert_sort:insertsort (); break;case bubble_sort:bubblesort (); Break;default : Break;}} /** * Insert sort */private void Insertsort () {for (int i = 1; i < a.length; i++) {int temp = A[i];int J = i-1;for (; j > = 0; j--) {if (A[j] > Temp) {a[j + 1] = A[j];} else {break;}} A[j + 1] = temp; Tools.print (a);}} /** * Bubble sort */private void Bubblesort () {for (int i = 0; i < a.length-1; i++) {for (int j = 0; J < a.length-i-1 ; J + +) {if (A[j] > a[j + 1]) {Tools.swap (A, J, J + 1);}}}}
Execution Result:
2. Disadvantages of this solution
Imagine that we are now going to add a quick sort order. What do we need to do?
① needs to change the client's run () method to add a case.
② There may also be a need to add a quicksort () method to the client.
That is, you must modify the client code when you need to extend the functionality.
In addition, if the specific sorting algorithm needs to be modified, then it is necessary to modify the client code. For example, if I want to modify the insert sort, I also need to modify the Client_notusestrategy class.
That is, when you need to modify the original functionality, you must also modify the client code.
This is not a good code structure as long as the client code needs to be modified. Because good code structure how can not meet the " closed to modify, open to expansion " principle of opening and closing ?
How can we modify it to meet the principle of opening and closing in this multi-branch structure? This leads to the strategy pattern.
Preliminary understanding of the Strategy model
What is the strategy model?
1. Definition of the policy model
The policy pattern defines a series of algorithms, encapsulates each algorithm, and allows them to be replaced with each other. The policy pattern makes the algorithm independent of the customers who use it.
2. When do I need to use policy mode?
There are a lot of if-else if– ...-else or switch–case ..., and these different operations belong to the same type of operation, but the policy mode can be used only when the specific processing method is different.
3. Composition of the policy model
1.UML figure
2. Role description
①istrategy: Policy interface;
②concretestrategy1, ConcreteStrategy2: The concrete strategy realizes, encapsulates the related algorithm and the behavior;
③context: The context used to manipulate the policy.
Using policy mode to solve problems
Now, we use the policy model to solve the sort problem we just encountered. Notice the difference between the Client_notusestrategy class and the Client_usestrategy class.
1. Code structure
2. IStrategy interface
/** * Policy interface * @author Zhenghaipeng */public interface istrategy {void sort (int[] a);}
3. Strategy_bubblesort-specific strategies for bubble sequencing
/** * Implements a bubbling sort of policy interface * * @author Zhenghaipeng */public class Strategy_bubblesort implements IStrategy {@Overridepublic void sort (int[] a) {for (int i = 0, i < a.length-1; i++) {for (int j = 0; J < a.length-i-1; + j) {if (A[j] > a[j + 1]) {Tools. Swap (A, J, J + 1);}}}}
4.strategy_insertsort the specific implementation strategy of the insertion sort
/** * Implements an insertion order for the policy interface * @author Zhenghaipeng */public class Strategy_insertsort implements IStrategy {@Overridepublic void sort (int[] A) {for (int i = 1; i < a.length; i++) {int temp = A[i];int J = i-1;for (; J >= 0; j--) {if (A[j] > Temp) {a[j + 1] = a[j];} else {break;}} A[j + 1] = temp; Tools.print (a);}}
5. Context Environment
/** * Context class, used to place policy * @author Zhenghaipeng */public class Context {IStrategy Strategy;public context (IStrategy strategy) {This.strateg y = strategy;} public void sort (int[] a) {this.strategy.sort (a);}}
6. Client code
/** * Client using policy mode * @author Zhenghaipeng */public class Client_usestrategy {istrategy strategy;int[] a;public client_usestrategy (ISt Rategy strategy, int[] a) {this.strategy = STRATEGY;THIS.A = A;} public void Run () {Context context = new Context (strategy); Context.sort (a);}}
7. Effect of execution
The result is the same as the result without using the policy mode.
8. Summary
In the above code, if we want to add a sort algorithm again, we just need to add a class that implements the IStrategy interface, such as a fast-row strategy_quicksort. Do you need to modify the client client_usestrategy? No need. The decoupling of the specific policy and the client is realized.
Counter-View client client_notusestrategy is not using the policy mode, and the client class must be modified if a new algorithm needs to be added.
Thinking about context in strategy mode 1. Is there any need for the context role to exist in the policy model?
This problem bothered me for a long time when I was learning strategy mode. As the above example, the context can not be completely. Here is the code after removing the context:
/** * No client with context * * @author Zhenghaipeng */public class Client_usestrategy_withoutcontext {istrategy strategy;int[] A;pub Lic Client_usestrategy_withoutcontext (IStrategy strategy, int[] a) {this.strategy = STRATEGY;THIS.A = A;} public void Run () {//original/context context = new context (strategy);//Context.sort (a);//Do not Contextthis.strategy.sort (a); }}
As you can see, it is also possible to perform the same effect. And the pros and cons are the same as in the context. Is that context really useless? It's definitely not.
2. Role of the context role – eliminate redundant code and improve code reusability
Suppose we need to calculate a different sort of time, how can we do it? Here are two ways to think about which is better.
① can add the calculation time code in the Run () method of the client-side code, as follows:
/** * Client using policy mode * * @author Zhenghaipeng */public class Copyofclient_usestrategy_withoutcontext {istrategy strategy;int[] A;p Ublic Copyofclient_usestrategy_withoutcontext (IStrategy strategy, int[] a) {this.strategy = STRATEGY;THIS.A = A;} public void Run () {//the original//Long startTime = System.currenttimemillis ();//Context context = new context (strategy);//CONT Ext.sort (a);//Long EndTime = System.currenttimemillis ();//Long Usedtime = endtime-starttime;//System.out.println ("The row The time for the order to be used is: "+ usedtime);//Do not contextlong StartTime = System.currenttimemillis (); This.strategy.sort (a); Long endTime = System.currenttimemillis (); Long usedtime = Endtime-starttime; System.out.println ("The time this sort is used is:" + Usedtime);}}
② Add the calculation time code to the context as follows:
/** * New Context class * @author Zhenghaipeng * @since June 5, 2015 */public class Copyofcontext {istrategy strategy;public copyofcontext (ISt Rategy strategy) {this.strategy = strategy;} public void sort (int[] a) {Long startTime = System.currenttimemillis (); This.strategy.sort (a); Long endTime = System.currenttimemillis (); Long usedtime = Endtime-starttime; System.out.println ("The time this sort is used is:" + Usedtime);}}
Which Way is better? Especially if you need to add more code.
Obviously, we should not add the client without the care of the code in the client. So it's much more reasonable to add code in the context.
From the point of view of code reuse, when there are multiple clients, adding a bunch of identical timing codes to each client is obviously too redundant. The use of the context eliminates these redundancies .
Assuming there are 100 client classes, one day the boss lets change the code, the same code will have to be changed 100 times. But if you put it in context, you just have to modify it once, and the benefits of code reuse are reflected.
3. Role of the context role – meeting the Open/closed principle
In the example above, IStrategy's sort (int[] a) method has only one parameter. Suddenly one day, the demand changed, the parameters became two (int[] A, float[] b). How should you modify the code?
① If there is no context: we need to change the code in each client code this.strategy (a) to This.strategy (A, B). This does not meet the opening and closing principle!
② If there is a context: we simply modify the sort (int[] a) method in the context class, and the client code is unaffected.
The use of strategy mode in Android development
Here's an example of using a strategy model in Android development.
Handler is often used in Android development. Handler is typically placed in activity, where a child thread sends a message to the activity via handler and then handles different messages in the way of Switch (msg.what). This can cause the following problems:
① need to define a number of constants for Case XXX. Child threads need to call these constants when they are sent, which increases the coupling between classes.
② when processing a lot of message types, there will be a large number of case branches, activity Class code line of the number of swish go up, very bloated. The task of an activity class is very heavy, and just a handler of hundreds of lines of code is a scary thing. (This is a lot of things that need activity to deal with this design, but it is said that in the past I/O Conference, Google has introduced the Data binding to Android, have time to learn ~)
③ does not meet the opening and closing principle.
The following is only the activity code, the rest of the code is in the attachment at the end of the text. Simulates downloading pictures and text from a server in two sub-threads. The message is then sent to the activity via handler and displayed on the interface. The policy mode is used when handler processing MSG.
1. Activity without using the policy mode
/** * @author Zhenghaipeng * @since June 5, 2015 */public class Notusestrategy extends Activity {/** * download picture from server, message handler for */publi C static final int msg_download_image_finshed = 100;/** * Get Friend list End from server */public static final int msg_get_contains_finsh = 101; Handler Handler; LinearLayout bglayout; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (r.layout.activity_main); bglayout = (linearlayout) Findviewbyid (R.id.bgLayout); Inithandler (); New Thread_downloadimage1 (Handler, this). Start (); New Thread_getcontains1 (Handler). Start (); /** * Initialize handler */private void Inithandler () {handler = new handler (new Handler.callback () {@Overridepublic Boolean Handl EMessage (Message msg) {//Msg.what different handling of various operations switch (msg.what) {//When the picture has been downloaded, add to the view case msg_download_image_finshed:// Create a new Imageviewimageview ImageView = new ImageView (notusestrategy.this);//Get the Bitmapbitmap bitmap = (bitmap) passed in from the child thread msg.obj;//set the ImageView image to the incoming image imageview.setimagebitmap (bitmap);// Add ImageView to view Bglayout.addview (ImageView); break;//when a contact is downloaded, add to view case Msg_get_contains_finsh:textview TextView = new TextView (notusestrategy.this); string s = (string) msg.obj;textview.settext (s); Bglayout.addview (textView); break;default:break;} return false;}});}}
2. Activity after using the policy mode
public class Usestrategy extends Activity {//Use Policy mode no more pre-defining a bunch of messages. Reduced coupling. Handler Handler; LinearLayout bglayout; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (r.layout.activity_main); bglayout = (linearlayout) Findviewbyid (R.id.bgLayout); Inithandler (); New Thread_downloadimage2 (Handler, this, Bglayout). Start (); New Thread_getcontains2 (Handler, this, bglayout). Start ();} /** * Initialize handler */private void Inithandler () {handler = new handler (new Handler.callback () {@Overridepublic Boolean Handl EMessage (Message msg) {//Use policy mode, do not write a heap switch-case//get incoming policy istrategy strategy = (istrategy) msg.obj;// Put the strategy in context to execute mycontext context = new Mycontext (strategy); Context.run (); return false;}});}}
3. Running
4. Evaluation
With the policy mode, the three lines of code in the Inithandler () method can be processed regardless of how many more cases are added later. The code in the entire Actiivty class needs little modification (and will not be modified in this method). There is no need to predefine some msg, and the coupling is very low.
Code Download http://download.csdn.net/detail/h28496/8782581
Reprint Please specify Source: http://blog.csdn.net/h28496/article/details/46403815
A detailed description of the "design mode" policy model