看了刘伟老师的设计模式里面的策略模式,做一下后面的练习题。算法的封装与切换——策略模式(四)_刘伟技术博客-CSDN博客史上最全设计模式导学目录(完整版)_刘伟技术博客-CSDN博客
练习
Sunny软件公司欲开发一款飞机模拟系统,该系统主要模拟不同种类飞机的飞行特征与起飞特征,需要模拟的飞机种类及其特征如表24-1所示:
为将来能够模拟更多种类的飞机,试采用策略模式设计该飞机模拟系统。
表24-1 飞机种类及特征一览表
首先分析问题,首先具体对象是飞机, 飞机有不同的种类(直升机,客机,歼击机,鹞式战斗机),然后飞机有两个动作,一个是起飞,一个是飞行,不同种类的飞机这两个动作会有不同的特征。这里我们定义一个抽象类Air , 定义3个方法 起飞takeOff(), 飞行fly(), 开始飞行 startFly();其中开始飞行方法里面调用起飞和飞行(这里用到的是就是模板方法模式模板方法模式深度解析(一)_刘伟技术博客-CSDN博客_模板方法模式)。
这里还可以细分,一次完整的飞行操作包括:起飞,飞行,降落3个步骤。还可以把降落方法定义出来,放在:开始飞行 startFly() 里面。
package com.pattern.strategy.abs;
public abstract class Air {
protected String name;
public Air(String name) {
this.name = name;
}
/**
* 起飞
*/
public abstract void takeOff();
/**
* 飞行
*/
public abstract void fly();
//降落
public void land(){
System.out.println(name + "降落!");
}
/**
* 开始飞行
*/
public void startFly(){
System.out.println(name + "开始飞行!");
takeOff();
fly();
land();
}
}
然后定义不同的飞机,飞机继承Air
package com.pattern.strategy;
import com.pattern.strategy.abs.Air;
//客机
public class AirPlane extends Air {
public AirPlane(String name) {
super(name);
}
@Override
public void takeOff() {
System.out.println(name + "长距离起飞(LongDistanceTakeOff)");
}
@Override
public void fly() {
System.out.println(name + "亚音速飞行(SubSonicFly)");
}
}
//歼击机
public class Fighter extends Air {
public Fighter(String name) {
super(name);
}
@Override
public void takeOff() {
System.out.println(name + "长距离起飞(LongDistanceTakeOff)");
}
@Override
public void fly() {
System.out.println(name + "超音速飞行(SuperSonicFly)");
}
}
//鹞式战斗机
public class Harrier extends Air {
public Harrier(String name) {
super(name);
}
@Override
public void takeOff() {
System.out.println(name + "垂直起飞(VerticalTakeOff)");
}
@Override
public void fly() {
System.out.println(name + "超音速飞行(SuperSonicFly)");
}
}
//直升机
public class Helicopter extends Air {
public Helicopter(String name) {
super(name);
}
@Override
public void takeOff() {
System.out.println(name + "垂直起飞VerticalTakeOff");
}
@Override
public void fly() {
System.out.println(name + "亚音速飞行(SubSonicFly)");
}
}
定义好后可以测试了:在测试这里定义了一个Map来存储飞机和类之间的关系,通过main函数里面的参数args来传入具体飞机,
package com.pattern.strategy;
import com.pattern.strategy.abs.Air;
import java.util.HashMap;
import java.util.Map;
public class Client {
public static void main(String[] args){
if(args.length == 0){
System.out.println("飞机名称不正确");
return;
}
Map<String,String> airMap = new HashMap<>();
airMap.put("直升机","com.pattern.strategy.Helicopter");
airMap.put("客机","com.pattern.strategy.AirPlane");
airMap.put("歼击机","com.pattern.strategy.Fighter");
airMap.put("鹞式战斗机","com.pattern.strategy.Harrier");
String name = args[0];
String className = airMap.get(name);
if(className == null){
System.out.println("飞机名称不正确");
return;
}
try {
//找到飞机对应的class
Class clazz = Class.forName(className);
//创建飞机对象
Air air = (Air) clazz.getDeclaredConstructor(String.class).newInstance(name);
//飞机起飞
air.startFly();
}catch (Exception e){
e.printStackTrace();
System.out.println("飞机事故");
}
}
}
传入具体参数:
运行结果:
直升机开始飞行!
直升机垂直起飞VerticalTakeOff
直升机亚音速飞行(SubSonicFly)
直升机降落!
总结:策略模式和工厂模式一起用能比较容易的解决策略的选择问题。同一件事如果需要按照顺序执行不同的步骤,可以使用模板方法模式来实现。