GitHub source code sharing

Wechat search: code nong StayUp

Home address: goZhuyinglong.github. IO

Source: github.com/gozhuyinglo…

1. A simple duck game

Let’s take a look at a duck simulation game: the game will appear all kinds of ducks, they swim and play water, quack.

After some research, the known Duck species are Mallard Duck, Redhead Duck and Rubber Duck. Known duck behaviors include Swim, Quack, and Display.

Here’s what the ducks look like:

Clear needs, let’s go!

1.1 It’s time to show OO technology

For reusability, we design a Duck superclass, Duck, and let various ducks inherit this superclass:

  • Implemented in the superclassswim(),quack()Method, because each kind of duck looks different, sodisplay()Specified as an abstract method (of course this class is also an abstract class).
  • The subclasses are implementeddisplay()methods
  • Since a rubber duck can’t “quack,” it’s rewrittenquack()The method is squeak.

Here is the UML class diagram:

1.2 Change!!

We know one of the unchanging truths of software development: change!

Now add a duck behavior: Fly. How do you do that?

If inheritance continues, the rubber duck will not fly and will need to rewrite the fly() method. As follows:

Then add another Duck: Decoy Duck, a wooden Duck that can’t bark or fly……

It seems that inheritance is not enough!

1.3 How about using interfaces?

Separate the fly() method from the quack() method and create an interface for the duck that owns the behavior to implement. As follows:

That seems to solve the problem for now!

But what if there were 100 more ducks? Wouldn’t all the ducks that could fly or quack have to be implemented once, without achieving the reuse of the code? And it would be a pain to change a behavior (like changing all squeaks to emulation squawks)…

1.4 Package Changes

There is one design principle that applies exactly to the duck simulation above.

Identify changes that may need to be made in your application and isolate them from code that doesn’t need to be changed.

In other words, if an area of code changes every time a new requirement comes in, then you can be sure that that area of code needs to be isolated from the rest of the stable code.

This is the spirit of the strategic pattern, and let’s take a look at it in detail.

2. Policy mode

Strategy Pattern is a behavioral Pattern. The pattern defines a series of algorithms, encapsulates them one by one, and makes them interchangeable. This pattern makes changes to the algorithm independent of the customers using it.

Define a family of algorithms, encapsulate each one, and make them interchangeable.

The design pattern embodies several design principles:

  • Packaging changes
  • Program for interfaces, not implementation classes
  • Use composition more than inheritance

The strategy pattern consists of three parts:

  • Strategy

Defines a common interface for all policies. Context uses this interface to invoke a ConcreteStrategy.

  • ConcreteStrategy

The implementation of the Strategy interface defines a specific policy implementation.

  • Context

Defines how the Strategy object is to be used and is the caller of the Strategy algorithm.

3. Code implementation

We used strategy mode to implement the simulated duck game above.

3.1 Flight behavior realization

Define the flight behavior interface

public interface Fly {
    void fly(a);
}
Copy the code

Fly with wings to implement classes

public class FlyWithWings implements Fly {
    @Override
    public void fly(a) {
        System.out.println("Fly on the wings."); }}Copy the code

Will not fly implementation class

public class FlyNoWay implements Fly {
    @Override
    public void fly(a) {
        System.out.println("Can't fly"); }}Copy the code

3.2 Realization of duck crow behavior

Define duck call behavior interface

public interface Quack {
    void quack(a);
}
Copy the code

Implementation class

public class QuackGuaGua implements Quack {
    @Override
    public void quack(a) {
        System.out.println("Quack"); }}Copy the code

Squeaks implementation class

public class QuackZhiZhi implements Quack {
    @Override
    public void quack(a) {
        System.out.println(squeak); }}Copy the code

It’s not called an implementation class

public class QuackNoWay implements Quack {
    @Override
    public void quack(a) {
        System.out.println("Can't bark."); }}Copy the code

3.3 Implementation of duck class

Define the duck abstract class

public abstract class Duck {

    protected Fly fly;
    protected Quack quack;

    public void swim(a) {
        System.out.println("Swimming...");
    }

    public abstract void display(a);

    public Fly getFly(a) {
        return fly;
    }

    public Quack getQuack(a) {
        returnquack; }}Copy the code

Mallard implementation class

public class MallardDuck extends Duck {

    // The wild duck flies on its wings and quacks
    public MallardDuck(a) {
        this.fly = new FlyWithWings();
        this.quack = new QuackGuaGua();
    }

    @Override
    public void display(a) {
        System.out.println("The appearance is mallard."); }}Copy the code

Redhead duck implementation class

public class RedheadDuck extends Duck {

    // The red-headed duck flies on its wings and quacks
    public RedheadDuck(a) {
        this.fly = new FlyWithWings();
        this.quack = new QuackGuaGua();
    }

    @Override
    public void display(a) {
        System.out.println("The appearance of a red-headed duck."); }}Copy the code

Rubber duck implementation class

public class RubberDuck extends Duck {

    // Rubber ducks can't fly and squeak
    public RubberDuck(a) {
        this.fly = new FlyNoWay();
        this.quack = new QuackZhiZhi();
    }

    @Override
    public void display(a) {
        System.out.println("Looks like a rubber duck."); }}Copy the code

Decoy duck implementation class

public class DecoyDuck extends Duck {

    // Decoy ducks can't fly or cry
    public DecoyDuck(a) {
        this.fly = new FlyNoWay();
        this.quack = new QuackNoWay();
    }

    @Override
    public void display(a) {
        System.out.println("The appearance is a decoy duck."); }}Copy the code

3.4 test

Write simple test classes

public class Test {

    public static void main(String[] args) {
        MallardDuck mallardDuck = new MallardDuck();
        mallardDuck.display();
        mallardDuck.swim();
        mallardDuck.getFly().fly();
        mallardDuck.getQuack().quack();

        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");

        DecoyDuck decoyDuck = newDecoyDuck(); decoyDuck.display(); decoyDuck.swim(); decoyDuck.getFly().fly(); decoyDuck.getQuack().quack(); }}Copy the code

The output

The appearance is that mallard is swimming... Fly with wings quack ------------------- appearance is bait duck is swimming... Can't fly can't barkCopy the code

4. Complete code

For the complete code, please visit my Github. If it is helpful to you, you are welcome to give a Star. Thank you!

Github.com/gozhuyinglo…

Reference 5.

  • Head First Design Patterns
  • Design Patterns: The Foundation of Reusable Object-oriented Software

Recommended reading

  • The singleton pattern