Java设计模式学习笔记——策略模式

88 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

首先来看看策略模式的概念

策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

(例子参考自《HeadFirst设计模式》)

现在假设有一类鸭子,每类鸭子都有不同的行为,有的可以呱呱叫,有的不能叫,还有的甚至可以飞……

一般的做法就是定义一个Duck的抽象类,把他可能拥有的各类行为都放进去,有多种变化行为的动作定义成抽象类:

public abstrack class Duck {
	public void swim(){
		System.out.println("每个鸭子都会游泳");
	}
	public abstract void quack();	//鸭子叫
	public abstract void fly();		//鸭子飞
}

但是这样会导致很多问题,比如:如果有五种鸭子的quack行为都是呱呱叫,那么在这五种鸭子的类中会存在相同的代码,在运行的时候也不能动态的改变他们的行为(万一有一种鸭子叫着叫着叫不出来了怎么办),而且这样我们很难得知鸭子的全部行为。

于是我们可以这样做,把鸭子的各种行为分离开来:

//飞行行为的接口
public interface FlyBehavior {
	public void fly();	
}
//不能飞的实现
public class FlyWithNoWay implements FlyBehavior{
	@Override
	public void fly() {
		System.out.println("当前鸭子不能飞");
	}
}
//能飞的实现
public class FlyWithWings implements FlyBehavior{
	@Override
	public void fly() {
		System.out.println("当前鸭子正在飞");
	}
}
//叫声行为的接口
public interface QuackBehavior {
	public void quack();
}
//呱呱叫行为的实现
public class Quack implements QuackBehavior{
	@Override
	public void quack() {
		System.out.println("当前鸭子呱呱叫");
	}
}
//无法发声行为的实现
public class MuteQuack implements QuackBehavior{
	@Override
	public void quack() {
		System.out.println("当前鸭子不能叫");
	}
}

然后我们再修改一下Duck类:

public abstract class Duck {
	
	FlyBehavior flyBehavior;
	
	QuackBehavior quackBehavior;
	
	public Duck() {}

	public void swim() {
		System.out.println("鸭子在游泳"); //假设所有的鸭子都会游泳,所以这里直接写出方法体
	}
	
	public abstract void display();

	public void performFly() {
		flyBehavior.fly();
	}
	
	public void performQuack() {
		quackBehavior.quack();
	}
	
	//后期可以动态改变飞行的行为
	public void setFlyBehavior(FlyBehavior flyBehavior) {
		this.flyBehavior = flyBehavior;
	}
	
	//后期可以动态改变叫声的行为
	public void setQuackBehavior(QuackBehavior quackBehavior) {
		this.quackBehavior = quackBehavior;
	}
}

我们来写几个具体的鸭子测试一下

public class NormalDuck extends Duck{
	
	public NormalDuck() {
		quackBehavior = new Quack();	//定义叫声的行为
		flyBehavior = new FlyWithNoWay();	//定义飞行的行为
	}

	@Override
	public void display() {
		System.out.println("这是一只正常的鸭子");
	}

}
public class NomalDuckTest {

	public static void main(String[] args) {
		Duck normalDuck = new NormalDuck();
		normalDuck.display();
		normalDuck.performFly();
		normalDuck.performQuack();
	}

}

运行结果:

2020101215430143.png

我们也可以在运行过程中动态的改变鸭子的行为:

public class ModelDuck extends Duck{
	
	public ModelDuck() {
		flyBehavior = new FlyWithWings();
		quackBehavior = new Quack();
	}

	@Override
	public void display() {
		System.out.println("这是一只玩具鸭");
	}

}
public class ModelDuckTest {

	public static void main(String[] args) {
		Duck modelDuck = new ModelDuck();
		modelDuck.display();
		modelDuck.performFly();
		modelDuck.performQuack();
		System.out.println("玩具鸭摔了一下");
		modelDuck.setQuackBehavior(new MuteQuack());
		modelDuck.performQuack();
	}

}

2020101215471416.png

我们可以看到我们手动把玩具鸭摔一下,然后他就叫不出来了