从自我理解的角度上看,策略模式,策略即为
办法/解决方法,对于某个问题,一般能够衍生出多种解决方法。当然,策略模式中的策略应该也是这个由来,在解决问题时,能够有多种方案/办法
或者说策略。
应用场景:
1. 比如我出行,我可以坐飞机、坐高铁、坐火车、轮船 或者是自己开车
2. 比如说在销售的时候商家是满300-30 还是或者是打折 ,采用哪种策略能够使得方案最佳。
由此,引出策略模式的定义:
在大话设计模式中的定义是这样的。
策略模式: 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
贴下书上策略模式结构图
优点:
策略类之间可以自由切换
由于策略类都实现同一个接口,所以使它们之间可以自由切换。
易于扩展
增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“
避免使用多重条件选择语句(if else),充分体现面向对象设计思想。
缺点:
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
策略模式三大要素
环境(Context):有一个Strategy类的引用,和具体的策略类交互。
抽象策略(Strategy)角色:一个接口或抽象类,给出规范。
具体策略(ConcreteStrategy)角色:具体算法或行为。
某电影院售票系统为不同类型的用户提供了不同的打折方式(Discount),学生凭学生证可享受8折优惠(StudentDiscount),儿童可享受减免10元的优惠(ChildrenDiscount),VIP用户除享受半价优惠外还可以进行积分(VIPDiscount)。策略模式类图如下:
抽象类Discount定义策略的折扣方法,并抽象出来一个公共属性。
package strategy;
/**
* @Author Tang
* 抽象策略(Discount)角色:一个接口或抽象类,给出规范。
**/
public abstract class Discount {
// 每种策略的优惠政策
public double discountPrice;
public abstract double calculate(double price);
}
儿童门票
package strategy;
/**
* @Author Tang
**/
public class ChildrenDiscount extends Discount{
public ChildrenDiscount(double price){
this.discountPrice =price;
}
@Override
public double calculate(double price) {
return price - discountPrice;
}
}
学生门票
package strategy;
/**
* @Author Tang
* 具体策略 学生策略
**/
public class StudentDiscount extends Discount{
public StudentDiscount(double discountPrice) {
this.discountPrice = discountPrice;
}
@Override
public double calculate(double price) {
return price * discountPrice;
}
}
VIP门票
package strategy;
/**
* @Author Tang
* VIP策略
**/
public class VIPDiscount extends Discount{
public VIPDiscount(double price){
this.discountPrice = price;
}
@Override
public double calculate(double price) {
return price * discountPrice;
}
}
定义Context为MovieTicket ,这里需要有一个Discount的引用
package strategy;
/**
* @Author Tang
* 环境 Context 有一个Strategy的引用
**/
public class MovieTicket {
// Strategy的引用
private Discount discount = null;
private double price;
public MovieTicket(Discount discount){
this.discount = discount;
}
// 计算逻辑 计算出优惠后的价钱
public void setPrice(double price){
// 调用每个具体策略的方法来分别计算出价格
this.price = discount.calculate(price);
}
public double getPrice(){
return this.price;
}
public void setDiscount(Discount discount){
this.discount =discount;
}
}
package strategy;
import java.util.Scanner;
/**
* @Author Tang
**/
public class StrategyTest {
private static double totalPrice;
public static void main(String[] args) {
while(true){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入打折方案:");
String str = scanner.next();
MovieTicket ticket = null;
switch (str){
case "学生优惠":
ticket = new MovieTicket(new StudentDiscount(0.8));
break;
case "儿童优惠":
ticket = new MovieTicket(new ChildrenDiscount(10));
break;
case "会员优惠":
ticket = new MovieTicket(new VIPDiscount(0.5));
break;
}
System.out.println("请输入门票原价:");
double oriPrice =scanner.nextInt();
ticket.setPrice(oriPrice);
System.out.println("优惠后的票价为:"+ ticket.getPrice());
}
}
}