The introduction

Please don’t catch “pattern disease”… In the future, if you can even write “Hello World” with patterns, that means you are sick… . This record is kept for future reference

demand

This article starts with the duck, a cute and tasty little animal, but today we won’t talk about how to eat it, but how to gracefully implement some of the duck’s specific behaviors.

  1. Every duck can swim and quack.
  2. In fact, some ducks can fly and some ducks can’t.
  3. Give the duck rocket power and make it a rocket powered duck.
  4. Program for interfaces, not implementations

One, the realization of duck superclass

public abstract class Duck {
	/ / call
	public void quack(a){}
	/ / swimming
	public void swim(a){}
	// Feature method
	public abstract void display(a);
}
Copy the code

The duck superclass determines that the duck has three properties: == call ==, == swim ==, ==display==.

Change the behavior of some ducks

At this point you might say, well, isn’t there a superclass inheritance? Yeah, you’re right. Here comes our first question: suppose there are already many ducks, and some of them need to be able to fly, what would be a good way to achieve this?

Write a flight method for the duck superclass?

/ / flight
public void fly(a) {
	System.out.print("I'm a flying duck.");
}
Copy the code

This will result in all duck subclasses having flight characteristics, not just some.

Discard inheritance and use interfaces

Since inheritance can not perfect the implementation of the function, so have to find a new way to find a new way to solve the problem, first, think of the interface. Quack () and fly() can be separated from ==Duck==. Create Iquack and Ifly interfaces, and let the ducks that need to implement Quack and FLY implement those interfaces. This is so much better than inheritance. No more rubber ducks hooting in the sky.

But this creates more duplicate code, which can be handled when there are fewer subclasses that need to be modified. Modifying the behavior of hundreds or thousands of ducks would be complicated. Using interfaces solves part of the problem, but it makes the code unusable. It’s just jumping from one nightmare to another. Even among flying ducks, flight behavior is variable. Maybe one duck uses rocket power to fly

Fourth, clarify the question again

So far, I have not found a good way to solve the problem.

  1. Inheritance does not solve the problem well, because the behavior of the duck changes constantly in the subclasses.
  2. The interface solved the problem, butjavaInterfaces do not have implementation code, so inheriting interfaces cannot achieve code reuse

5. Strategic mode

The strategy pattern addresses this problem by identifying changes in your application that may need to be made, isolating them from code that doesn’t need to be changed. According to this idea, the changes to isolate are quack() and fly(). And we’re going to be programming for interfaces, not for implementations, and we’re going to define the two interfaces QuackBehavior and FlyBehavior first

New implementation

Create FlyWithWings class IFlyBehavior // create FlyNoWay class IFlyBehavior // create Quack class IQuackBehavior // create Squeak class IQuackBehavior // can talk

This design allows the == fly == and == call == to be reused by other objects, because these actions are irrelevant to ==Duck==, and the new actions will not affect the existing behavior classes.

public interface IFlyBehavior {
	void fly(a);
}
public interface IQuackBehavior {
	void quack(a);
}
Copy the code

Then add both interfaces to the duck superclass as a whole.

public abstract class Duck {
	public IFlyBehavior iFlyBehavior;
	public IQuackBehavior iQuackBehavior;
	/ / swimming
	public void swim(a) {}
	// Feature method
	public abstract void display(a);
	/ / execution
	public void performFly(a) {
		iFlyBehavior.fly();
	}
	/ / implementation
	public void performQuack(a) { iQuackBehavior.quack(); }}Copy the code

Using the interface instance, delegate fly and Quack to the behavior class so that when instantiating the duck object, you can make the duck implement a specific behavior based on its behavior. Use specific behavior classes when instantiating behavior.

public class RedDuck extends Duck {
	public RedDuck(a) {
		iFlyBehavior = new FlyWithWings();
		iQuackBehavior = new Quack();
	}
	@Override
	public void display(a) {
		System.out.println("Red Duck"); }}Copy the code

At this point, our design has finally succeeded. Seven, test,

Taking this one step further, it is possible to dynamically change the behavior of the duck at run time. The above implementation needs to customize the behavior of the duck in the constructor. Now the Duck is no longer a quacking Duck, it can fly through the air by separating Duck from behavior, reducing coupling, improving reuse, and most importantly, improving the scalability of the code how to change the behavior of the Duck at run time. First, let’s think about the behavior interface instance in Duck. Change the behavior of the duck at run time by changing the implementation of the interface. Add setter methods that dynamically set the implementation of the duck subclass behavior interface

public static void main(String[] args) {
   	RedDuck redDuck = new RedDuck();
   	redDuck.setiFlyBehavior(new Rocket());
   	redDuck.performFly();
   }
Copy the code

Results: Rocket-powered flight

Unconsciously, the program has been perfected, which is amazing, and this is the Strategy Pattern.

Reference: Head First Java