许多商家为了提高知名度或是其他原因会进行商品促销活动。而有时对于新老客户的促销策略又有所不同。比如新客户打9折,老客户打8折。(当然,这只是比喻)我们可以用简单的程序来表示这种促销活动。
public class Merchandise {
//新客户
public final static int NEW_CUSTOMER = 0;
//老客户
public final static int OLD_CUSTOMER = 1;
public static void main(String[] args) {
Merchandise merchandise = new Merchandise();
float price = 90l;
System.out.println(merchandise.calculatePrice(NEW_CUSTOMER, price));
System.out.println(merchandise.calculatePrice(OLD_CUSTOMER, price));
}
//根据类型计算商品价格
public float calculatePrice(int customer, float price) {
if (customer == NEW_CUSTOMER) {
return newCustomerPrice(price);
} else if (customer == OLD_CUSTOMER) {
return oldCustomerPrice(price);
}
return price;
}
//计算新客户价格
public float newCustomerPrice(float price) {
return (float) (price * 0.9);
}
//计算老客户价格
public float oldCustomerPrice(float price) {
return (float) (price * 0.8);
}
}
一个简单的程序就出来了:
81.0
72.0
但是,这却隐藏着一个问题,假设现在老板说有一种特殊的客户,可以打5折。现在要修改程序,就需要添加多一个if判断了:
public float caculatePrice(int customer, float price) {
if (customer == NEW_CUSTOMER) {
return newCustomerPrice(price);
} else if (customer == OLD_CUSTOMER) {
return oldCustomerPrice(price);
} else if (customer == SPECIAL_CUSTOMER) {
return specialCustomerPrice(price);
}
return price;
}
会发现,如果老板说又多了一种客户,就会在程序中多出现一个if else语句,导致程序显得越来越臃肿。既然对于每种客户都采取不同的策略,那么接下来用策略模式来解决上述问题。
UML图:
Context:操纵策略的环境
Strategy:策略的抽象
ConcreteStragety:策略的具体实现
按照图示,可以尝试先定义一个接口,用来计算价格:
//计算价格的接口,对应Strategy
public interface CaculateStrategy {
/**
* 计算价格
* @param price
* @return
*/
float caculatePrice(float price);
}
分别有新老,特殊三种客户,并且都实现了计算价格的接口:
//新客户价格策略,对应ConcreteStrategyA
public class NewCustomer implements CaculateStrategy{
@Override
public float caculatePrice(float price) {
return (float) (price * 0.9);
}
}
//老客户价格策略,对应ConcreteStrategyB
public class OldCustomer implements CaculateStrategy{
@Override
public float caculatePrice(float price) {
return (float) (price * 0.8);
}
}
有了客户,最后需要一个价格计算器:
//价格计算,对应Context
public class PriceCalculator {
CaculateStrategy strategy;
public static void main(String[] args) {
PriceCalculator calculator = new PriceCalculator();
//设置价格策略
OldCustomer oldCustomer = new OldCustomer();
calculator.setStrategy(oldCustomer);
System.out.println("老客户:" + calculator.calculatePrice(90l));
}
public void setStrategy(CaculateStrategy strategy) {
this.strategy = strategy;
}
public float calculatePrice(float price) {
return strategy.caculatePrice(price);
}
}
结果:
老客户:72.0
用上述方式,如果要添加一个特殊客户,就会显得轻便许多,省去了if else的臃肿逻辑:
public class SpecialCustomer implements CaculateStrategy{
@Override
public float caculatePrice(float price) {
return (float) (price * 0.5);
}
}
策略模式的优缺点
- 优点
- 结构清晰,容易扩展,耦合度低,体现了单一职责的设计原则。
- 缺点
- 使用的子类会增多。