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 superclass
swim()
,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 implemented
display()
methods - Since a rubber duck can’t “quack,” it’s rewritten
quack()
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