Java design pattern----------policy mode

Source: Internet
Author: User

The following is from the Headfirst design mode book and http://www.cnblogs.com/xrq730/p/4906313.html's blog post, as their own learning notes summarized below.

Headfirst design mode A book at the beginning of the three principles of design:

1. Find out where changes may be needed in your application, isolate them, and don't mix with the code that needs to change.

2. Programming for interfaces, not for implementation.

3. Multi-use combination, less inheritance.

The policy pattern------defines the family of algorithms, which are encapsulated separately so that they can be replaced by each other, which allows the algorithm to change independently of the client using the algorithm.

Take the duck game Simuduck in the book as an example to analyze:

Duck Game Simuduck has a variety of ducks, there are swimming and quack functions, the original Super class as shown:

Later, in order to add the fly function to some ducks, the programmer Joe added fly () directly to the parent class, causing the super-parent class to become:

This causes all ducks to have the function of flying, which is obviously illogical. And in the same vein, not all ducks have quack functions, such as rubber ducks. So the programmer Joey Will quack () and Fly () two methods are drawn out, implemented into two interfaces quackable and flyable, as long as the duck will be flying to achieve quackable interface can be flown to achieve flyable interface can be.

But this leads to the problem that the code can not be reused, each duck subclass, as long as the fly will have to implement the Flyable Interface Fly () once, if there are 100 flying Ducks subclass, this fly method must be the same writing 100 times, which is obviously unreasonable.

At this point, apply the above three design principles:

1. Separation of changes and invariant------The duck class is still the superclass of all ducks, but the flight and the behavior of each duck subclass are different, and the two behaviors need to be taken out, abstracted into behavioral interfaces Flybehavior and Quackbehavior;

2. Programming for interfaces rather than for implementation----------the behavior of ducks into specialized behavior classes, which need to implement the corresponding behavior interfaces instead of implementing the behavior interfaces by the Duck class. Such a design can make these behavior classes are reused by other objects, such as the Swan can also fly, wild geese can fly, frogs can also be a quack, which makes these behaviors and ducks are irrelevant.

3. Multi-use combination, less inheritance-------------each duck subclass has an instantiated object for the Flybehavior and Quackbehavior interfaces, allowing the Ducks to handle the behavior by both objects. Unlike previous practices, we can see that the behavior of a duck is not inherited but rather is combined with an instantiated object of the behavior interface. The object and instantiation of the Duck object and behavior with this behavior is the has-a relationship.

The implementation is as follows:

Parent class:

 PackageTest; Public Abstract classduck{Quackbehavior quackbehavior;//Note that the type of object being held is the interface type Flybehavior flybehavior;  Public voidswim () {System.out.println ("I can Swim"); }     Public Abstract voiddisplay ();  Public voidPerformquack () {//Call the corresponding behavior method Quackbehavior.quack (); }     Public voidPerfromfly () {flybehavior.fly (); }     Public voidSetquackbehavior (Quackbehavior quackbehavior) {//The behavior can be dynamically set This. quackbehavior=Quackbehavior; }     Public voidSetflybehavior (Flybehavior flybehavior) { This. Flybehavior =Flybehavior; }}

Flight interface

 Package Test;  Public Interface Flybehavior {    publicvoid  fly ();}

Quack Call Interface

 Package Test;  Public Interface Quackbehavior {    publicvoid  quack ();}

Specific behavior implementation:

 package   Test;  public  class  Flywithwings implements   Flybehavior {@Override 
    public  void      Fly () {System.out.println ( "I have a pair of invisible wings to fly with Me" 
 package   Test;  public  class  Flynoway implements   Flybehavior {@Override public  void      Fly () {System.out.println ( "I can ' t fly" 
 Package Test;  Public class Implements Quackbehavior {    @Override    publicvoid  quack () {        System.out.println ( "Quack");}    }

Test class:

 Package Test;  Public class Miniducksimulator {    publicstaticvoid  main (string[] args) {        Duck Mallard=new  Mallardduck ();        Mallard.display ();        Mallard.performquack ();        Mallard.perfromfly ();        Mallard.setflybehavior (new  Flynoway ());        Mallard.perfromfly ();    }}

Output:

Summary of the Strategy model

The following is transferred from: http://www.cnblogs.com/xrq730/p/4906313.html

Policy mode

The intent of the policy pattern is to encapsulate each algorithm in a separate class with a common interface for a set of algorithms, so that they can be replaced with each other. The policy pattern allows the algorithm to change without affecting the client.

Structure of the policy pattern

The strategy pattern is the wrapper over the algorithm , which separates the responsibility of using the algorithm and the algorithm itself. The strategy pattern is usually to wrap a series of algorithms into a series of policy classes, as subclasses of an abstract policy class.

The policy model involves three roles:

1. Environmental role

Hold a reference to a policy strategy

2. Abstract policy role

This is an abstract role, usually implemented by an interface or abstract class that gives the interfaces required for all specific policy classes

3. Specific policy roles

Wrapping a related algorithm or behavior

Example of a policy pattern

There is an abstract policy interface:

Public interface strategy{public    void Usestrategy ();}

Two specific strategies are implemented:

public class Strategya implements strategy{public    void Usestrategy ()    {        System.out.println (" Strategya.usestrategy () ");}    }

public class Strategyb implements strategy{public    void Usestrategy ()    {        System.out.println (" Strategyb.usestrategy () ");}    }

A class holds a reference to a policy:

public class context{    private strategy strategy;        Public Context (Strategy strategy)    {        this.strategy = strategy;    }        public void Strategymethod ()    {        strategy.usestrategy ();    }}

Where you call this class, you can decide which strategy to use in your own way:

public class testmain{public    static void Main (string[] args)    {        strategy Strategya = new Strategya ();        Strategy strategyb = new Strategyb ();                Context context = new context (Strategya);        Context.strategymethod ();        Context = new context (STRATEGYB);        Context.strategymethod ();    }}

Usage Scenarios for Policy mode

1. Shopping System

Give me a practical example. If there is a shopping system, when the user pays, there will be a lot of scenes, according to the different circumstances of users to calculate the amount of different users to pay, this time the most intuitive approach is:

On the inside of the payment write n many if...else If...else, judge the user's scene, calculate the user payment amount according to the scene.

This design clearly violates the opening and shutting principle. Opening and closing principle of "closed" refers to the modification is closed, but if there are several more algorithms, then you must modify the payment class again.

In this way, you can use the policy mode. In the payment class, there is a reference to a payment interface, and each time a specific strategy is introduced according to the different scenarios. For example, to use the S0 algorithm in Class A, a S0 strategy is passed in, and in class B the S1 algorithm is used to pass in a S1 algorithm. No need to put judgment in the payment class, the code is more readable and maintainable. Payment This class can even generate a. class file directly in a jar package for invocation.

2. Make the code more elegant and easier to maintain

If you have a scoring system somewhere in your code, you write a very long logic for this scoring system, and one day, the product department's colleagues look for you and give me a score logic, at this point, there are two ways:

(1) The original scoring logic to delete, but do a disadvantage is not to see the previous scoring algorithm, another drawback is that if the scoring algorithm to change back will not find the code, although the SVN and GIT version management tool has the function of historical commit record, but still appear troublesome

(2) Comment The original scoring logic, but the biggest drawback is that there is a lot of comment in the code, especially when the policy logic is very long, which leads to very poor readability of the code.

At this point, you can use the policy mode, the scoring logic is abstracted as a strategy, the scoring strategy, a new implementation of the policy class, and finally the code to pass in the new policy implementation class.

Application and interpretation of strategy mode in Java

The application of the policy mode in Java, this is too obvious, because comparator this interface is simply for the strategy model of the birth. The difference between comparable and comparator in the article, detailed the use of comparator. For example, there is a sort method in collections, because the elements inside the collection are likely to be composite objects, and composite objects are not like basic data types, and can be sorted by size, how are compound objects sorted? Based on this problem, Java requires that if the defined compound object has a sort function, it can implement the comparable interface or the comparator interface by itself, and look at the overloaded method with comparator in the sort:

1 public static <T> void sort (list<t> List, comparator<? super T> C) {2     object[] A = List.toarray (); 3     Arrays.sort (A, (Comparator) c); 4     Listiterator i = List.listiterator (); 5 for     (int j=0; j<a.length; j + +) {6         i.next (); 7         I.set (A[j]); 8     }9     }

Follow the 3rd line:

1 public static <T> void sort (t[] A, comparator<? super T> C) {2     t[] aux = (t[]) A.clone () 3         if (C==nul L) 4             mergesort (aux, A, 0, a.length, 0); 5         else6             mergesort (aux, A, 0, a.length, 0, C); 7     }

The incoming c is not NULL, follow the mergesort of line 6th:

 1 private static void MergeSort (object[] src, 2 object[] dest, 3 int low, int. High, I      NT off, 4 Comparator c) {5 int length = high-low; 6 7//insertion sort on smallest arrays 8  if (length < Insertionsort_threshold) {9 for (int i=low; i

Line 10th, the return result of the class's compare method based on the comparator interface determines whether to swap (swap).

This is the strategy mode, we can give collections's sort method into different comparator implementation classes as a different comparison strategy. Different comparison strategies, for the same set, may produce different sorting results.

Recognize strategy patterns

It should be understood that the focus of the strategy pattern is not how to implement the algorithm (just as the focus of the factory pattern is not how to produce a specific subclass in the factory), but how to organize, invoke these algorithms, so that the program structure more flexible, with better maintainability and extensibility. Software development takes much longer to complete than development time, because there may be changes in customer requirements, so we should be committed to improving maintainability and scalability. The strategy mode reduces the coupling degree between programs, which makes the maintenance of the program easier.

A big feature of the strategy model is the equality of the strategy algorithms . For a series of specific strategy algorithms, everyone's position is exactly the same, because of this equality, each algorithm can be replaced each other.

During runtime, only one specific policy implementation object can be implemented at a time, although it is possible to dynamically switch between different policies.

Advantages and disadvantages of the strategy model

Advantages

1, avoid the multiple conditions If...else if...else statement, multi-conditional statements are not easy to maintain

2, the policy mode provides a way to manage related algorithm clusters, proper use of inheritance can move public code to the parent class, thus avoiding code duplication

Disadvantages

1. The client must know all the policy classes and decide which policy to use, which means that the client must understand the differences between the algorithms in order to select the appropriate algorithm

2, if there are many alternative strategies, the data of the object will be many

Another good example is: Transfer from https://www.cnblogs.com/wuyudong/p/5924223.html

For example, calculate the fares required for buses and subways to run after a specified distance

Package Com.wuyudong.strategy.normal;public class Pricecalculator {//bus type private static final int bus = 1;    Metro type private static final int SUBWAY = 2;        public static void Main (string[] args) {pricecalculator calculator = new Pricecalculator ();        System.out.println ("Bus fare for 10 km:" + calculator.calculateprice (bus));    System.out.println ("The fare for the 10-kilometer subway is:" + calculator.calculateprice (SUBWAY));        }//Calculate bus price private int busprice (int km) {int extratotal = km-10;        int extrafactor = EXTRATOTAL/5;        int fraction = extratotal% 5;        int price = 1 + extrafactor * 1; return fraction > 0?    ++price:price;        //calculate metro price private int subwayprice (int km) {if (km <= 6) {return 3;        } else if (Km > 6 && miles <) {return 4;        } else if (Km < n && km >) {return 5; } else if (km < 32 && km > (6) {return;    } return 7; }//According to the type to calculate the corresponding price private int calculateprice (int km, int type) {if (type = = BUS) {return busprice        (km);        } else {return subwayprice (km); }    }}

If you add another taxi's price calculation, add the corresponding code:

public class Pricecalculator {    //bus type    private static final int bus = 1;    Metro type    private static final int SUBWAY = 2;    Taxi type    private static final int TAXI = 3;    public static void Main (string[] args) {        Pricecalculator calculator = new Pricecalculator ();        System.out.println ("Bus fare for 10 km:"                + calculator.calculateprice (bus));        System.out.println ("The fare for the 10-kilometer subway is:"                + calculator.calculateprice (SUBWAY));    }    Calculate Taxi price    private int Taxiprice (int km) {        return km * 2;    }    Calculates the corresponding price by type    private int calculateprice (int km, int type) {        if (type = = BUS) {            return busprice (km); 
   

It can be seen that the above code is more coupled, and whenever a new type of vehicle is added, a lot of code needs to be constantly modified, which is reconstructed using the policy mode:

First define an abstract price-computing interface:

Compute interface Public interface Calculatestrategy {    int calculateprice (int. km);}

Each method of travel defines a separate calculation strategy class:

Bus calculation strategy

public class Busstrategy implements Calculatestrategy {public    int calculateprice (int. km) {        int extratotal = km- Ten;        int extrafactor = EXTRATOTAL/5;        int fraction = extratotal% 5;        int price = 1 + extrafactor * 1;        return fraction > 0? ++price:price;}    }

Subway calculation strategy

public class Subwaystrategy implements Calculatestrategy {public    int calculateprice (int miles) {        if (km <= 6) {
   return 3;        }  else if (km > 6 && miles <) {            return 4;        } else if (km < && miles >) {            return 5;        } else if (km < + && km > $) {            return 6;        }        return 7;}    }

Then create a role that plays the context, with the following code:

public class Tranficcalculator {    calculatestrategy mstrategy;        public static void Main (string[] args) {        Tranficcalculator calculator = new Tranficcalculator ();        Set the calculation Strategy        calculator.setstrategy (New Busstrategy ());        Calculate Price        System.out.println ("bus by 10 km Price:" + Calculator.calculateprice);            }        public void Setstrategy (Calculatestrategy mstrategy) {        this.mstrategy = mstrategy;    }    public int Calculateprice (int miles) {        return mstrategy.calculateprice (km);    }}

This way, even if you need to add a taxi's price calculation, simply create a new class that inherits from the Calculatestrategy interface and implements the method.

Java design pattern----------policy mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.