需求:
某电影院开发一套影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票打折方式,具体打折方案如下:
1. 学生凭学生证可享受票价8折优惠。
2. 年龄在10周岁及以下的儿童可以享受每张票减10元的优惠(原始票价需大于等于20元)
3. 影院VIP用户除享受半价优惠外可进行积分,积分累计到一定额度可换取电影院赠送的奖品。
该系统在未来可能还要根据需要引入新的打折方式。
传统方案:
在电影票类MovieTicket中增加一个计算票价的方法calculate()
带来的问题:1) calculate()方法的代码非常庞大,包含过多if---else语句,不利于测试和维护。 2)增加新的打折方式时,需要修改MovieTicket类的源码,违反的开闭原则。 3)算法的复用性差,
class MovieTicket{
private double price;
private String type;
public void setPrice(double price){
this.price=price;
}
public void setType(String type){
this.type=type;
}
public double getPrice(){
return this.calculate();
}
public double calculate(){
if(this.type.equalsIgnoreCase("student")){
System.out.println("学生票");
return this.price*0.8;
}else if(this.type.equalsIgnoreCase("children")&& this.price>=20){
System.out.println("儿童票");
return this.price-10;
}else if(this.type.equalsIgnoreCase("vip")){
System.out.println("VIP");
System.out.println("积分增加!")
return this.price*0.5;
}else{
return this.price;
}
}
}
class Client{
public static void main(String[] args){
MovieTicket mt=new MovieTicket();
double originalPrice=60.0;
double currentPrice;
mt.setPrice(priginalPrice);
mt.setType("Student");
System.out.println("折后价:"+mt.getPrice());
}
}
改进===>使用策略模式
定义
定义一些独立的类 [即 策略类] 来封装不同的算法,每一个类封装一种具体的算法。
策略模式的目的:将算法的定义与使用分开。 即算法的行为与环境分开
class MovieTicket{
private doble price;
private Discount discount;
public void setPrice(double price){
this.price=price;
}
public double getPrice(){
retrun discount.calculate(this.price);
}
}
interface Discount{
public double calculate(double price);
}
class StudentDiscount implements Discount{
@override
public double calculate(double price){
return price*0.8;
}
}
class ChildrenDiscount implements Discount{
@override
public double calculate(double price){
return price-10;
}
}
class VIPDiscount implements Discount{
@override
public double calculate(double price){
return price*0.5;
}
}
class Client{
public static void main(String[] args){
MovieTicket mt=new MovieTicket();
mt.setPrice(60.0);
SutdentDiscount studentDiscount=new StudentDiscount();
mt.setDiscount(studentDiscount);
double currentPrice=mt.getPrice();
System.out.println(currentPrice);
}
}
策略模式的注意事项和细节
- 策略模式的关键是:分析项目中变化部分与不变部分
- 策略模式的核心思想是:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性
- 体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为) 即可,避免了使用多重转移语句(if..else if..else)
- 提供了可以替换继承关系的办法: 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展
- 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞