设计模式-策略模式学习及案例演示

设计模式-策略模式学习及案例演示

概念

  • 定义

    • 定义一组算法,将每个算法都封装起来,并且使他们之间可以互换(继承和多态)
  • 使用场景

    • 代码中如果有大量的if…else…
    • 系统中有很多类,而他们的区别仅仅在于他们的行为不同
    • 一个系统需要动态地在几种算法中进行选择
  • 类型

    • 行为型
  • 优点

    • 满足了开闭原则
    • 避免使用多重条件转移语句
    • 提高算法的保密性和安全性
  • 缺点

    • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类
    • 会产生很多策略类
  • 结合使用的设计模式

    • 策略模式-工厂模式
    • 策略模式-状态模式
    • 策略模式-代理模式

Coding

业务背景

假设网购商城存在 普通用户、普通会员、高级会员三个角色,三个角色都需要进行下单操作,不同会员的的折扣不同,已经积分计算方式也不同。系统需要对不同的角色进行不同的操作。

在基于上述的背景,下面进行代码编写,并一步步演进。

实现方式一:

package com.dsdj.behavioral.strategy;

/**
 * TODO
 *
 * @author dsdj
 * @version 1.0
 * @className Demo1
 * @date 2019/5/12 下午6:50
 **/
public class Demo1 {

    // 普通用户
    private static final String ROLE_PTYH = "PTYH";
    // 普通会员
    private static final String ROLE_PTHY = "PTHY";
    // 高级会员
    private static final String ROLE_GJHY = "GJHY";

    public static void main(String[] args) {

        // 角色名称 普通用户
        String roleName = ROLE_PTHY;
        double price = 23.5;
        if(ROLE_PTYH.equals(roleName)){
            System.out.println("无折扣:"+price+"元");
            System.out.println("积分增加5分.....");
        } else if(ROLE_PTHY.equals(roleName)){
            System.out.println("普通会员8折:"+price*0.8+"元");
            System.out.println("积分增加10分....");
        } else if (ROLE_GJHY.equals(roleName)){
            System.out.println("高级会员5折:"+price*0.5+"元");
            System.out.println("积分增加20分....");
        }
    }
}

输出

普通会员8折:18.8元
积分增加10分....

从实现方式一可以看到代码使用了大量的if…else…,同时代码扩展不易,如果增加了一个角色修改不易,并且一个方法中可能会造成大量代码,也不符合代码规范。

基于上述的不足,我们进一步演进代码。

实现方式二

通过分析,不同的角色的折扣和积分有不同的算法(策略),那么我们可以使用策略模式进行抽取包装。

定义各个策略以及策略的抽象

抽象类

package com.dsdj.behavioral.strategy;

public interface DiscountStrategy {

    /**
     * 折扣操作
     */
    void discountOperate(Double price);
}

普通用户的折扣方式

package com.dsdj.behavioral.strategy;
public class PTYHDiscountStrategy implements DiscountStrategy{
    public void discountOperate(Double price) {
        System.out.println("无折扣:"+price+"元");
        System.out.println("积分增加5分.....");
    }
}

普通会员的折扣方式

package com.dsdj.behavioral.strategy;
public class PTHYDiscountStrategy implements DiscountStrategy{
    public void discountOperate(Double price) {
        System.out.println("普通会员8折:"+price*0.8+"元");
        System.out.println("积分增加10分....");
    }
}

高级会员的折扣方式

package com.dsdj.behavioral.strategy;

/**
 * 高级会员
 *
 * @author dsdj
 * @version 1.0
 * @className PTHYDiscountStrategy
 * @date 2019/5/12 下午7:13
 **/
public class GJHYDiscountStrategy implements DiscountStrategy{
    public void discountOperate(Double price) {
        System.out.println("高级会员5折:"+price*0.5+"元");
        System.out.println("积分增加20分....");
    }
}


封装各策略

package com.dsdj.behavioral.strategy;

/**
 * 包装类
 **/
public class DiscountActivity {

    private DiscountStrategy discountStrategy;

    public DiscountActivity(DiscountStrategy discountStrategy){
        this.discountStrategy = discountStrategy;
    }

    public void doDiscount(Double price){
        discountStrategy.discountOperate(price);
    }



}

测试类(高层模块)

package com.dsdj.behavioral.strategy;

/**
 * TODO
 *
 * @author dsdj
 * @version 1.0
 * @className Demo1
 * @date 2019/5/12 下午6:50
 **/
public class Demo1 {

    // 普通用户
    private static final String ROLE_PTYH = "PTYH";
    // 普通会员
    private static final String ROLE_PTHY = "PTHY";
    // 高级会员
    private static final String ROLE_GJHY = "GJHY";

    public static void main(String[] args) {

        // 角色名称 普通用户
        String roleName = ROLE_PTHY;
        double price = 23.5;
        DiscountActivity discountActivity = null;

        if(ROLE_PTYH.equals(roleName)){
            discountActivity = new DiscountActivity( new PTYHDiscountStrategy());
        } else if(ROLE_PTHY.equals(roleName)){
            discountActivity = new DiscountActivity(new PTHYDiscountStrategy());
        } else if (ROLE_GJHY.equals(roleName)){
            discountActivity = new DiscountActivity( new GJHYDiscountStrategy());
        }
        discountActivity.doDiscount(price);
    }
}

总结:在实现方式二中,我们对策略进行抽取并封装了,高层模块屏蔽了对具体细节的实现。但是代码中还是存在大量if…else…

针对上述的问题,下面我们结合工厂模式,对代码进一步改造

实现方式三

定义一个策略工厂

package com.dsdj.behavioral.strategy;

import java.util.HashMap;
import java.util.Map;

/**
 * 策略工厂
 **/
public class DiscountStrategyFactory {
    // 普通用户
    public static final String ROLE_PTYH = "PTYH";
    // 普通会员
    public static final String ROLE_PTHY = "PTHY";
    // 高级会员
    public static final String ROLE_GJHY = "GJHY";

    private static final Map<String,DiscountStrategy> map = new HashMap();
    static {
        map.put(ROLE_PTYH,new PTYHDiscountStrategy());
        map.put(ROLE_PTHY,new PTHYDiscountStrategy());
        map.put(ROLE_GJHY,new GJHYDiscountStrategy());
    }

    private DiscountStrategyFactory(){

    }
    public static DiscountStrategy getDiscountStrategy(String roleName){
        DiscountStrategy discountStrategy = map.get(roleName);
        return  discountStrategy == null? null:discountStrategy;
    }
}

测试类

package com.dsdj.behavioral.strategy;


public class Demo1 {
    public static void main(String[] args) {

        // 角色名称 普通用户
        String roleName = DiscountStrategyFactory.ROLE_GJHY;
        double price = 23.5;
        DiscountActivity discountActivity = new DiscountActivity(DiscountStrategyFactory.getDiscountStrategy(roleName));
        discountActivity.doDiscount(price);
    }
}

总结:结合工厂模式使用之后,代码的可读性就增加了,也复合开闭原则,对增加了代码的扩展性。

Spring中用到的策略模式举例

在spring中也有很多地方用到了策略模式。
设计模式-策略模式学习及案例演示_第1张图片

你可能感兴趣的:(设计模式)