Java的23种设计模式:策略模式实战

小七学习网,助您升职加薪,遇问题可联系:客服微信【1601371900】 备注:来自网站

策略模式是一种行为型设计模式,定义一系列算法,把每一个算法都封装到一个独立类中,从而使各个算法之间可以自由切换。 本文详细介绍了策略模式的代码分析、测试方法、优缺点、使用场景等,并贴出完整代码和提供下…

策略模式是一种行为型设计模式,定义一系列算法,把每一个算法都封装到一个独立类中,从而使各个算法之间可以自由切换。

本文详细介绍了策略模式的代码分析、测试方法、优缺点、使用场景等,并贴出完整代码和提供下载链接。

本文你将会获得以下知识:

  1. 策略模式的简单实现完整代码
  2. 电商优惠券场景的策略模式完整代码
  3. 游戏角色切换武器场景的策略模式完整代码
  4. 策略模式的优缺点
  5. 策略模式的使用场景

适合人群:Java中高级开发。



一、前言

在日常项目开发过程中,个人感觉运用策略模式来设计某个功能中存在多个独立算法并且每个算法都可以自由切换的业务场景,比如:电商使用优惠券下单场景,每一种优惠券就是一种策略,用户可以自由选择不同的优惠券下单,不但可以提升个人设计水平,而且还可以彰显个人技术魅力征服公司上级领导或者漂亮开发美眉。

二、概念介绍

  1. 抽象策略角色(Strategy) 通常是一个抽象类,定义通用方法。
  2. 具体策略角色(ConcreteStrategy) 继承抽象策略角色(Strategy)并重写其方法,实现具体算法。
  3. 上下文角色(Context) 起到承上启下的作用,持有抽象策略类的实例引用,可以非常方便的切换策略。

    各个组件之间的关系图如下: 在这里插入图片描述

三、代码分析

  1. 代码结构 在这里插入图片描述
  2. 策略模式的简单实现方式 下面代码是策略模式最简单直接的实现方式,首先创建一个抽象策略角色类定义通用方法;其次创建三个具体策略角色类都继承抽象策略类,并实现各自的具体算法;最后创建一个上下文角色类,并持有抽象策略实例引用,代码如下:
    /** * 抽象策略角色,定义通用方法 */public abstract class Strategy {
    //算法public abstract void algorithm();
    } /** * 具体策略角色 */ public class ConcreteStrategy1 extends Strategy {
    @Overridepublic void algorithm() {    System.out.println(\"算法1\");}
    } /** * 具体策略角色 */ public class ConcreteStrategy2 extends Strategy {
    @Overridepublic void algorithm() {    System.out.println(\"算法2\");}
    } /** * 具体策略角色 */ public class ConcreteStrategy3 extends Strategy {
    @Overridepublic void algorithm() {    System.out.println(\"算法3\");}
    } /** * 上下文角色 */ public class Context { //持有抽象策略实例引用 Strategy strategy;
    public Context(Strategy strategy) {    this.strategy = strategy;}/** * 根据策略执行算法 */public void executeStrategy() {    strategy.algorithm();}
    } /** * 策略模式测试代码 */ public class TestForStrategy1 {
    public static void main(String[] args) {    Context context;    //不同策略执行不同的算法    //策略1执行算法1    context = new Context(new ConcreteStrategy1());    context.executeStrategy();    //策略2执行算法2    context = new Context(new ConcreteStrategy2());    context.executeStrategy();    //策略3执行算法3    context = new Context(new ConcreteStrategy3());    context.executeStrategy();}
    } 
  3. 电商优惠券场景的策略模式实现方式 下面是拿了一个电商使用优惠券下单的场景进行讲解并编码,把优惠权当作独立的算法策略,即不同的优惠券使用不同的算法计算订单价格。

    首先创建一个优惠券抽象策略类,定义通用的计算订单价格方法;其次创建两个具体策略类,分别是满减券策略和折扣券策略类,并实现各自优惠券的具体算法,比如:满减券必须超过某个金额才能使用等等;最后创建一个优惠券上下文类,并持有优惠券抽象策略实例引用和定义客户端调用的方法规范,代码如下:

    /** * 订单信息 */public class Order {    //商品id    private String productId;    //价格    private double price;
    public Order(String productId, double price){    this.productId = productId;    this.price = price;}public double getPrice() {    return price;}public void setPrice(double price) {    this.price = price;}public String getProductId() {    return productId;}public void setProductId(String productId) {    this.productId = productId;}
    } /** * 抽象策略角色,优惠券抽象策略 */ public abstract class CouponStrategy {
    /** * 计算订单的价格 * @param order * @return */public abstract double computePrice(Order order);
    } /** * 具体策略角色,满减券策略,MJ是满减的缩写 */ public class MJCouponStrategy extends CouponStrategy {
    /** * 优惠金额 */private double discountPrice;public MJCouponStrategy(double discountPrice){    this.discountPrice = discountPrice;}@Overridepublic double computePrice(Order order) {    //订单金额必须大于优惠金额    if(order.getPrice() > discountPrice){        return order.getPrice() - discountPrice;    }else {        return 0;    }}
    } /** * 具体策略角色,折扣券策略,ZK是折扣的缩写 */ public class ZKCouponStrategy extends CouponStrategy {
    /** * 折扣 */private double rate;public ZKCouponStrategy(double rate){    this.rate = rate;}@Overridepublic double computePrice(Order order) {    return order.getPrice() * rate;}
    } /** * 上下文角色,优惠券上下文 */ public class CouponContext {
    private CouponStrategy strategy;public CouponContext(CouponStrategy strategy){    this.strategy = strategy;}/** * 根据策略计算订单的价格 * @param order * @return */public double executeStrategy(Order order){    return strategy.computePrice(order);}
    } /** * 电商优惠券场景的策略模式测试代码 */ public class TestForStrategy2 {
    public static void main(String[] args) {    //订单对象    Order order = new Order(\"001\",1000);    //优惠券上下文    CouponContext context;    //订单最终价格    double finalPrice;    //不同策略(即优惠券)计算出不同的价格    //满减券策略(满1000减100)    context = new CouponContext(new MJCouponStrategy(100));    finalPrice = context.executeStrategy(order);    System.out.println(\"原价:1000,使用满减券(满1000减100)的最终价格:\"+finalPrice);    System.out.println(\"=====================================================\");    //折扣券策略(8.8折)    context = new CouponContext(new ZKCouponStrategy(0.88));    finalPrice = context.executeStrategy(order);    System.out.println(\"原价:1000,使用折扣券(8.8折)的最终价格:\"+finalPrice);}
    } 
  4. 游戏角色切换武器场景的策略模式实现方式 下面是拿了一个游戏角色切换武器的场景进行讲解并编码,游戏中有国王、将军和士兵三个角色,每个角色都有默认使用的武器,比如:国王使用剑、将军使用斧头、士兵使用长矛,每个角色都可以切换武器,比如:国王也可以使用长矛。首先创建一个武器抽象策略类,定义通用的使用武器(即策略)战斗方法;其次创建三个具体策略类,分别是剑武器策略、斧头武器策略和长矛武器策略;最后创建一个游戏角色抽象类(即充当上下文角色)持有武器抽象策略的实例引用,定义设置武器方法(即切换武器方法),再创建三个具体游戏角色继,都是继承游戏角色抽象类,代码如下:
    /** * 抽象策略角色,武器抽象策略 */public abstract class WeaponStrategy {
    /** * 使用武器(即策略)战斗 * @return */public abstract void fight();
    } /** * 具体策略角色,剑武器策略 */ public class SwordStrategy extends WeaponStrategy{
    @Overridepublic void fight() {    System.out.println(\"用“剑”攻击\");}
    } /** * 具体策略角色,斧头武器策略 */ public class AxeStrategy extends WeaponStrategy{
    @Overridepublic void fight() {    System.out.println(\"用“斧头”攻击\");}
    } /** * 具体策略角色,长矛武器策略 */ public class SpearStrategy extends WeaponStrategy{
    @Overridepublic void fight() {    System.out.println(\"用“长矛”攻击\");}
    } /** * 上下文角色,游戏角色,比如:国王、将军、士兵 * 每个角色可以随意切换武器(即策略) */ public abstract class Role { private WeaponStrategy weaponStrategy;
    public abstract void display();public void performFight() {    weaponStrategy.fight();}/** * 设置武器 * @param weaponStrategy */public void setWeaponStrategy(WeaponStrategy weaponStrategy) {    this.weaponStrategy = weaponStrategy;}
    } /** * 国王 */ public class KingRole extends Role {
    @Overridepublic void display() {    System.out.println(\"我是国王\");}
    } /** * 将军 */ public class GeneralRole extends Role {
    @Overridepublic void display() {    System.out.println(\"我是将军\");}
    } /** * 士兵 */ public class SoldierRole extends Role {
    @Overridepublic void display() {    System.out.println(\"我是士兵\");}
    } /** * 游戏使用武器场景的策略模式测试代码 */ public class TestForStrategy3 {
    public static void main(String[] args) {    //国王角色    Role kingRole = new KingRole();    //用剑    kingRole.setWeaponStrategy(new SwordStrategy());    kingRole.display();    kingRole.performFight();    //切换武器,用长矛    kingRole.setWeaponStrategy(new SpearStrategy());    kingRole.performFight();    System.out.println(\"=====================================================\");    //将军角色    Role generalrole = new GeneralRole();    //用斧头    generalrole.setWeaponStrategy(new AxeStrategy());    generalrole.display();    generalrole.performFight();    System.out.println(\"=====================================================\");    //士兵角色    Role soldierRole = new SoldierRole();    //用长矛    soldierRole.setWeaponStrategy(new SpearStrategy());    soldierRole.display();    soldierRole.performFight();}
    } 

四、代码测试

  1. 策略模式的简单实现方式,运行TestForStrategy1类中的main方法 控制台日志:
    算法1算法2算法3

    在这里插入图片描述

  2. 电商优惠券场景的策略模式实现方式,运行TestForStrategy2类中的main方法 控制台日志:
    原价:1000,使用满减券(满1000减100)的最终价格:900.0=====================================================原价:1000,使用折扣券(8.8折)的最终价格:880.0

    在这里插入图片描述

  3. 游戏角色切换武器场景的策略模式实现方式,运行TestForStrategy3类中的main方法 控制台日志: 我是国王 用“剑”攻击 用“长矛”攻击 ===================================================== 我是将军 用“斧头”攻击 ===================================================== 我是士兵 用“长矛”攻击 在这里插入图片描述

五、优缺点

优点:

  • 可以自由切换算法
  • 可以避免使用if-else和switch多重条件判断语句
  • 符合开闭原则,新增具体策略类不需修改上下文代码
  • 符合单一职责原则,每个具体策略类只负责自己的算法

缺点:

  • 一个策略创建一个类,具体策略类太多时,会加上代码维护难度
  • 不符合迪米特法则,客户端必须知道所有策略之间的区别才能选择合适的算法,违反最少知道原则

六、使用场景

  1. 需要避免一个类中过多使用if-else条件判断来执行对应算法的场景
  2. 需要自由切换算法的场景
  3. 不希望暴露算法的场景
  4. Java AWT中的布局管理器LayoutManager

七、总结

通过这次的策略模式实战,让我们掌握了策略设计模式是什么、策略模式代码如何编写及测试、优缺点及使用场景,学完本Chat内容后,可以快速把策略模式代码运用到日常开发中“肆无忌惮的装逼”,呵呵呵。

策略模式实战完整代码已上传到 Gitee,下载地址如下:https://gitee.com/romantic-pk/demo-strategy.git

PS:如有写错请指正,感谢您的阅读。

小七学习网,助您升职加薪,遇问题可联系:客服微信【1601371900】 备注:来自网站

免责声明: 1、本站信息来自网络,版权争议与本站无关 2、本站所有主题由该帖子作者发表,该帖子作者与本站享有帖子相关版权 3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和本站的同意 4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责 5、用户所发布的一切软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 6、您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 7、请支持正版软件、得到更好的正版服务。 8、如有侵权请立即告知本站(邮箱:1099252741@qq.com,备用微信:1099252741),本站将及时予与删除 9、本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章和视频仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。