设计模式之四策略模式
譬如商城有优惠策略,①优惠券抵扣,拼多多有月卡就是一种②返现促销,满100返回20.③拼团,拼多多的核心模式。下面我们用代码模拟这个场景,首先我们创建一个促销策略的接口PromotionStrategy。
Promotion促销的意思, Stragegy策略的意思
案例一
package com.hanker.io;
//创建策略接口
interface PromotionStrategy{
void doPromotion();//执行促销策略
}
//优惠券策略类
class CouponStrategy implements PromotionStrategy{
public void doPromotion() {
System.out.println("领取优惠券,商品价格直接减优惠券面值抵扣.");
}
}
//返现策略
class CashbackStrategy implements PromotionStrategy{
public void doPromotion() {
System.out.println("返现促销,返回的金额转到支付宝账号.");
}
}
//拼团策略
class GroupbuyStrategy implements PromotionStrategy{
public void doPromotion() {
System.out.println("拼团,满2人成团,全团享受团购特价");
}
}
//没有优惠策略
class EmptyStrategy implements PromotionStrategy{
public void doPromotion() {
System.out.println("无促销活动..");
}
}
//创建促销活动方案类
class PromotionActivity{
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public void execute() {
promotionStrategy.doPromotion();
}
}
public class StragegyPatternDemo {
public static void main(String[] args) {
//创建优惠券的促销策略
CouponStrategy couponStrategy = new CouponStrategy();
//创建返现的促销策略
CashbackStrategy cashbackStrategy = new CashbackStrategy();
//创建两个促销活动
PromotionActivity p618 = new PromotionActivity(couponStrategy);
PromotionActivity p1111 =new PromotionActivity(cashbackStrategy);
p618.execute();
p1111.execute();
}
}
代码到这里还有可以优化的地方,也就是营销策略最好集成存放,用户想使用哪种策略直接取出。
//为了管理方便做一个工厂类
class PromotionStrategyFactory{
//创建一个map存储所有的策略,管理方便
private static final Map<String,PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<>();
static {
PROMOTION_STRATEGY_MAP.put(PromotionKey.COUPON, new CouponStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashbackStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.GROUPBY, new GroupbuyStrategy());
}
//空策略
private static final PromotionStrategy NON_PROMOTION = new EmptyStrategy();
//获取策略的方法
public static PromotionStrategy getPromotionStrategy(String promotionKey) {
PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
}
//定义一个常量接口
static interface PromotionKey{
String COUPON = "COUPON";
String CASHBACK = "CASHBACK";
String GROUPBY = "GROUPBY";
}
}
客户端:
public class StragegyPatternDemo {
public static void main(String[] args) {
//key是一个普通字符串,很可能出现错误,如何解决:做一个常量
String promotionKey = PromotionStrategyFactory.PromotionKey.CASHBACK;
//从工厂获取一个策略
PromotionStrategy promotionStrategy = PromotionStrategyFactory.getPromotionStrategy(promotionKey);
//创建促销活动
PromotionActivity p51 = new PromotionActivity(promotionStrategy);
p51.execute();
}
}
案例二
网上支付的案例: 支付宝支付,微信支付,银联支付,京东白条支付;一个场景的应用场景是大家在支付的时候回提示选择支付方式,如果用户没有选择,系统也会使用默认的支付方式结算。
package com.hanker.io;
import java.util.HashMap;
import java.util.Map;
//支付状态类
class PayState{
private int code; //编码 200 一般是 ok
private Object data;//数据
private String msg;//提示信息
public PayState(int code, Object data, String msg) {
super();
this.code = code;
this.data = data;
this.msg = msg;
}
public String toString() {
return "支付状态:[" + code + "],"+ msg+",交易详情:"+data;
}
}
//策略抽象类
abstract class Payment{
//支付类型
public abstract String getName();
//查询余额
protected abstract double queryBalance(String uid);
//扣款支付 uid用户编号,amount支付金额
public PayState pay(String uid,double amount) {
if(queryBalance(uid) < amount) {
return new PayState(500,"支付失败","余额不足");
}
return new PayState(200,"支付成功","支付金额:"+amount);
}
}
//支付宝支付
class AliPay extends Payment{
@Override
public String getName() {
return "支付宝";
}
@Override
protected double queryBalance(String uid) {
return 900;
}
}
//微信支付
class WechatPay extends Payment{
public String getName() {
return "微信支付";
}
protected double queryBalance(String uid) {
return 256;
}
}
//银联支付
class UnionPay extends Payment{
public String getName() {
return "银联支付";
}
protected double queryBalance(String uid) {
return 120;
}
}
//京东支付
class JDPay extends Payment{
public String getName() {
return "京东支付";
}
protected double queryBalance(String uid) {
return 500;
}
}
//策略工厂类
class PaymentStrategyFactory{
public static final String ALI_PAY = "ALI_PAY";
public static final String JD_PAY = "JDPAY";
public static final String UNION_PAY = "UNION_PAY";
public static final String WECHAT_PAY = "WECHAT_PAY";
public static final String DEFAULT_PAY = ALI_PAY;//默认支付方式:支付宝
private static final Map<String,Payment> PAY_MAP = new HashMap<>();
static {
PAY_MAP.put(ALI_PAY, new AliPay());
PAY_MAP.put(JD_PAY, new JDPay());
PAY_MAP.put(UNION_PAY, new UnionPay());
PAY_MAP.put(WECHAT_PAY, new WechatPay());
}
public static Payment getPayment(String payKey) {
if( !PAY_MAP.containsKey(payKey) ) {
return PAY_MAP.get(DEFAULT_PAY);
}
return PAY_MAP.get(payKey);
}
}
//提交一个订单,调用支付方式
class Order{
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
super();
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public PayState pay() {
return pay(PaymentStrategyFactory.DEFAULT_PAY);
}
public PayState pay(String payKey) {
Payment payment = PaymentStrategyFactory.getPayment(payKey);
System.out.println("欢迎使用:"+payment.getName());
System.out.println("本次交易金额为:"+amount +",开始扣款.....");
return payment.pay(payKey, amount);
}
}
public class StragegyPatternDemo2 {
public static void main(String[] args) {
Order order = new Order("1001","202003180001",3000);
PayState payState = order.pay(PaymentStrategyFactory.ALI_PAY);
System.out.println(payState);
}
}
优缺点
优点:
①策略模式符合开闭原则
②策略模式可避免使用多重条件语句,如if—else语句、switch语句
③使用策略模式可以提高算法的保密性和安全性
缺点:
①客户端必须知道所有的策略,并且自行决定使用哪一个策略类
②代码中会产生非常多的策略类,增加了代码的维护难度。