Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.


Hello everyone, I’m Fangyuan, and this blog mainly refers to “Head First Design Pattern”.


1. I have a problem

I have a little duck that quacks every day. I’m bored. I want it to learn how to fly

public class RealDuck extends Duck {
    @Override
    public void quack(a) {
        super.quack(); }}Copy the code

It also inherits the base class Duck

public abstract class Duck {

    public void quack(a){
        System.out.println("Quack quack."); }}Copy the code

1.1 How do I make it fly?

  • First of all, I thought of it! I directly inThe base class Duck writes a method that fliesIsn’t that enough? Simple!
public abstract class Duck {

    public void quack(a){
        System.out.println("Quack quack.");
    }
    
    public void fly(a){
        System.out.println("I've learned to fly!"); }}Copy the code

Just a quick test

public class Test {
    public static void main(String[] args) {
        Duck myDuck = newRealDuck(); myDuck.quack(); myDuck.fly(); }}Copy the code

Well, the problem seems to be solved, but if the toy duck implements the base class, then the toy duck also flies!

public class Test {
    public static void main(String[] args) {
        Duck myDuck = new RealDuck();

        myDuck.quack();
        myDuck.fly();

        System.out.println("Toy Duck ↓");
        Duck toyDuck = newToyDuck(); toyDuck.fly(); }}Copy the code

What are we gonna do? The toy duck also flies, so I will rewrite the fly method in the toy duck, and that will solve the problem

public class ToyDuck extends Duck {
    @Override
    public void fly(a) {
        System.out.println("I'm a toy duck. I can't fly."); }}Copy the code

But looking back, think, I not only only toy duck ah, I have pet duck, Donald Duck, yellow duck and so on, a lot of ducks can not fly, each class to rewrite, is not very troublesome? And a lot of the code is duplicate, how to solve this problem?

1.2 I have a solution

  • Rule of design: Isolate parts of your application that may need to change, and don’t mix them with code that doesn’t change.

So let’s take the fiy() method out, but how do we get it out? Let’s look at the next design principle

  • Design principle: Program for the interface, not the implementation

Let’s take the example of duck flying. We define fly as FlyBehavior interface, and then use its implementation class to implement this interface to achieve different ways of flying (flying and not flying), ok? No understanding normal, I said not clear, look at the following code will understand

public interface FlyBehavior {
    void fyl(a);
}

public class CanFly implements FlyBehavior {
    @Override
    public void fyl(a) {
        System.out.println("I can fly"); }}public class CantFly implements FlyBehavior {
    @Override
    public void fyl(a) {
        System.out.println("I can't fly!"); }}Copy the code

The two implementation classes implement the FlyBehavior interface, achieving two methods of flying and not flying. In this way, this flying action can be reused by other objects, because these behaviors have no relationship with the duck and realize decoupling. Even if we add other behaviors, there is no need to modify the code of the duck.

1.3 Implement this method

We introduce the instance variable FlyBehavior interface into Duck as follows

public abstract class Duck {
    
    private FlyBehavior flyBehavior;

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public void quack(a){
        System.out.println("Quack quack.");
    }

    public void fly(a){ flyBehavior.fyl(); }}Copy the code

So we can do different actions for different ducks. Let’s try!

public class Test {
    public static void main(String[] args) {
        Duck myDuck = new RealDuck();
        myDuck.setFlyBehavior(new CanFly());
        myDuck.fly();

        System.out.println("Toy Duck ↓");
        Duck toyDuck = new ToyDuck();
        toyDuck.setFlyBehavior(newCantFly()); toyDuck.fly(); }}Copy the code

We finished designing the duck business, and we went back and looked at the big picture

This also embodies a design principle

  • Design principle: more assembly, less inheritance

Wait, listen to you all this time? What about strategic patterns? Ah? After listening to ducks without design patterns, I’m not doing it!

Wait a minute! Drop the knife! I’m telling you! I’m telling you!

2. Policy mode

In fact, the strategic model, has appeared, but the small did not mention it. Let’s take a look at the description. What does it say?

  • Policy pattern: It defines a family of algorithms, encapsulates them separately and makes them interchangeable. This pattern makes changes to the algorithm independent of the clients using the algorithm.

You see? All right, take it!

All right, put the knife down. I’ll keep talking. I’ll keep talking.

Take a look at what’s in the red box and compare the concepts. Do you get it? Let’s be clear, isn’t it, isn’t it, being able to switch between different behaviors? I’ll write the code and you’ll get it!

Write two new interface implementation classes

public class FlyStyleOne implements FlyBehavior {
    @Override
    public void fyl(a) {
        System.out.println("I will fly slowly first!"); }}public class FlyStyleTwo implements FlyBehavior {
    @Override
    public void fyl(a) {
        System.out.println("I'll fly faster!"); }}Copy the code

Test the

public class Test {
    public static void main(String[] args) {
        Duck myDuck = new RealDuck();
        myDuck.setFlyBehavior(new CanFly());
        myDuck.fly();

        myDuck.setFlyBehavior(new FlyStyleOne());
        myDuck.fly();

        myDuck.setFlyBehavior(newFlyStyleTwo()); myDuck.fly(); }}Copy the code

According to the results

Different ways of flying, corresponding to different algorithms, I can put these algorithms between the random change, that is, my duck, fly freely, want to fly how to fly, change the way of flying! This implements the policy pattern. Everything in front is foreshadowing. The strategic mode is here.

Ok, is that down?


Can see here, also reward a small FAFA bar ~