Strategy pattern of Java design pattern
- Prepare project questions
(1) There are all kinds of ducks (such as wild duck, Peking duck, water duck, etc. ducks have all kinds of behaviors, such as barking, flying, etc.)
(2) Display duck information - Basic introduction to strategy mode
(1) In Strategy Pattern, algorithm families (policy groups) are defined and encapsulated respectively so that they can be replaced with each other
Make the changes of the algorithm independent of the customers using the algorithm
(2) This algorithm embodies several design principles. First, separate the changed code from the unchanged code; Second, for interface programming rather than specific
Class (defines the policy interface); Third, use more combination / aggregation and less inheritance (customers use strategies through combination) - Schematic class diagram of strategy mode
The customer context has a member variable strategy or other policy interfaces
, we can specify which strategy to use in the constructor
- Strategy mode to solve duck problem
(1) Train of thought class diagram
Strategy mode: encapsulate the behavior interface, implement the algorithm family, put the behavior interface object in the superclass, and set the behavior object in the subclass. The principle is:
Separate the changing part, encapsulate the interface, and program various functions based on the interface. This mode makes the change of behavior independent of the user of the algorithm
(2) Code implementation
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
WildDuck wildDuck = new WildDuck();
wildDuck.fly();//
ToyDuck toyDuck = new ToyDuck();
toyDuck.fly();
PekingDuck pekingDuck = new PekingDuck();
pekingDuck.fly();
//Dynamically change the behavior of an object, Peking duck can't fly
pekingDuck.setFlyBehavior(new NoFlyBehavior());
System.out.println("The actual flying ability of Peking Duck");
pekingDuck.fly();
}
}
//Policy interface I
public interface FlyBehavior {
void fly(); // Subclass concrete implementation
}
//Policy interface II
public interface QuackBehavior {
void quack();//Subclass implementation
}
public class BadFlyBehavior implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println(" General flying skills ");
}
}
public class GoodFlyBehavior implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println(" Superb flying skills ~~~");
}
}
public class NoFlyBehavior implements FlyBehavior{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println(" Can't fly ");
}
}
//Abstract class aggregation policy interface object
public abstract class Duck {
//Properties, policy interface
FlyBehavior flyBehavior;
//Other attributes < - > policy interface
QuackBehavior quackBehavior;
public Duck() {}
public abstract void display();//Display duck information
public void quack() {
System.out.println("Ducks quack~~");
}
public void swim() {
System.out.println("Ducks can swim~~");
}
public void fly() {
//improvement
if(flyBehavior != null) {
flyBehavior.fly();
}
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
public class PekingDuck extends Duck {
//If Beijing ducks can fly, but their flying skills are average
public PekingDuck() {
// TODO Auto-generated constructor stub
flyBehavior = new BadFlyBehavior();
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("~~Peking duck~~~");
}
}
public class ToyDuck extends Duck{
public ToyDuck() {
// TODO Auto-generated constructor stub
flyBehavior = new NoFlyBehavior();
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("Toy duck");
}
//All methods of the parent class need to be overridden
public void quack() {
System.out.println("Toy ducks can't bark~~");
}
public void swim() {
System.out.println("Toy ducks can't swim~~");
}
}
public class WildDuck extends Duck {
//Constructor, object passed in FlyBehavor
public WildDuck() {
// TODO Auto-generated constructor stub
flyBehavior = new GoodFlyBehavior();
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println(" This is a wild duck ");
}
}
- Source code analysis of JDK arrays application in strategy mode
(1) The Comparator of JDK's Arrays uses the policy mode
(2) Code analysis + pattern role analysis
public class Strategy {
public static void main(String[] args) {
// TODO Auto-generated method stub
//array
Integer[] data = { 9, 1, 2, 8, 4, 3 };
// Realize descending sorting, return - 1 on the left, 1 on the right, and 0 remains unchanged
// explain
// 1. Implement Comparator interface (policy interface), anonymous class object new Comparator < integer > () {..}
// 2. Object new comparator < integer > () {..} Is the object that implements the policy interface
// 3. public int compare(Integer o1, Integer o2) {} specifies the specific processing method
Comparator<Integer> comparator = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
if (o1 > o2) {
return -1;
} else {
return 1;
}
};
};
// explain
/*
* public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a); //Default method
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c); //Using Policy Object c
else
// Object usage policy c
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
*/
//Mode 1
Arrays.sort(data, comparator);
System.out.println(Arrays.toString(data)); // Descending sort
//Mode 2 - simultaneous lambda expression implementation strategy mode
Integer[] data2 = { 19, 11, 12, 18, 14, 13 };
Arrays.sort(data2, (var1, var2) -> {
if(var1.compareTo(var2) > 0) {
return -1;
} else {
return 1;
}
});
System.out.println("data2=" + Arrays.toString(data2));
}
}
- Policy mode considerations and details
(1) The key of the strategy model is to analyze the changing part and the unchanged part of the project
(2) The core idea of the strategy model is: use more combination / aggregation and less inheritance; Use behavior class composition instead of behavior inheritance. More elastic
(3) It embodies the principle of "close to modification and open to extension". When adding behavior to the client, there is no need to modify the original code, just add a strategy (or behavior)
This avoids the use of multiple transition statements (if... else, if... else)
(4) It provides a way to replace the inheritance relationship: the policy pattern encapsulates the algorithm in a separate Strategy class, so that you can change it independently of its Context
Change it to make it easy to switch, understand and expand
(4) Every time you add a policy, you need to add a class. When there are too many policies, the number of classes will increase