本文主要讲解Java设计模式之策略模式
策略模式介绍
策略模式也叫政策模式,是一种行为型设计模式,也是父类与子类关系的一种模式。策略模式采用了面向对象的继承和多态机制。策略模式是定义了一系列宣发并将算法封装起来,使他们可以互相替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。
策略模式使用场景
1、多个类只有在算法或行为上稍有不同的场景。
2、算法需要自由切换的场景。
3、需要屏蔽算法规则的场景。
策略模式UML图如下:
说明:
Context:也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
Strategy:策略、算法家族的抽象。通常为接口,定义每个策略或算法必须具有的方法和属性。是策略的抽象。
ConreateStrategy:具体的策略实现。该类含有具体的算法。
策略模式使用实例
一批货物从A地运送到距离为500KM 的B地,有三种运送方式,选择一个比较便宜的方式,通过调研有如下三种方式:
分别是飞机、汽车、火车。三种方式价格不一样,飞机每千米50元,汽车是0.5元,火车是0.1元。下面就用策略模式实现下这三种方式分别的费用
1 Strategy,新建一个CalculateStragegy接口
//计算接口
public interface CalculateStrategy {
float price(int km);
}
2、ConcreteStrategy,新建CarStrategy,PlaneStrategy、TrainStrategy实现接口CalculateStrategy
//汽车
ublic class CarStrategy implements CalculateStrategy {
@Override
public float price(int km) {
return (float) 0.5 * km;
}
}
//飞机
public class PlaneStrategy implements CalculateStrategy {
@Override
public float price(int km) {
return 50 * km;
}
}
//火车
public class TrainStrategy implements CalculateStrategy {
@Override
public float price(int km) {
return (float) (0.1 * km);
}
}
3 Context ,新建Client
public class Client {
CalculateStrategy calculateStrategy;
static int km = 500;
public static void main(String[] args) {
Client client = new Client();
//飞机的方式
client.setCalculateStrategy(new PlaneStrategy());
System.out.println("乘坐飞机需要的费用为:¥" + client.getPrice(km));
//火车的方式
client.setCalculateStrategy(new TrainStrategy());
System.out.println("乘坐火车需要的费用为:¥" + client.getPrice(km));
//汽车的方式
client.setCalculateStrategy(new CarStrategy());
System.out.println("自己驾车需要的费用为:¥" + client.getPrice(km));
}
/**
* 设置运输方式
*
* @param calculateStrategy
*/
public void setCalculateStrategy(CalculateStrategy calculateStrategy) {
this.calculateStrategy = calculateStrategy;
}
/**
* 获得费用
*
* @param km
* @return
*/
public float getPrice(int km) {
return calculateStrategy.price(km);
}
策略模式优缺点
优点
1、算法可以自由切换。
2、结构清晰明了,使用简单直观。
3、操作封装更为彻底,简化了操作。
4、耦合度大大降低,只要实现接口即可,无需做其它修改。
缺点
1、随着策略的增加,策略类会越来越多
2、所有的策略都要暴露出去
策略模式的拓展
1、定义一个枚举类,实现方式如下:
public enum Calculator {
//汽车
CAR {
public float price(int km) {
return (float) 0.5 * km;
}
},
PLANE {//飞机
public float price(int km) {
return (float) 50 * km;
}
},
TRAIN {//火车
public float price(int km) {
return (float) 0.1 * km;
}
};
Calculator() {
}
public abstract float price(int km);
}
2、修改client
public class Client {
static int km = 500;
public static void main(String[] args) {
System.out.println("乘坐飞机需要的费用为:¥" + Calculator.PLANE.price(km));
System.out.println("乘坐火车需要的费用为:¥" + Calculator.TRAIN.price(km));
System.out.println("自己驾车需要的费用为:¥" + Calculator.CAR.price(km));
}
}
可以看出:
该例子的Calculator是一个枚举。
Calculator是一个浓缩了策略模式的枚举。
注意:
策略枚举是一个非常优秀和方便的模式,但是其受到枚举类型的限制,每个枚举项都是public、final、static的,拓展性受到了一定的约束,因此在开发中,枚举策略一般担当不了经常发生改变的角色。