• 设计模式13-行为型设计模式-策略设计模式


    编程是一门艺术,大批量的改动显然是非常丑陋的做法,用心的琢磨写的代码让它变的更美观。

    在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如超市促销可以釆用打折、送商品、送积分等方法。

    在软件开发中也常常遇到类似的情况,当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如数据排序策略有快速排序、归并排序、选择排序、二叉树排序等。

    如果使用多重条件转移语句实现(即硬编码),不但使条件语句变得很复杂,而且增加、删除或更换算法要修改原代码,不易维护,违背开闭原则。如果采用策略模式就能很好解决该问题。

    1.策略设计模式定义

    策略(Strategy)模式:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

    2.策略设计模式的有点与不足

    策略模式的主要优点:

    • 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。
    • 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
    • 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
    • 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
    • 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

    策略设计模式的不足:

    • 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。

    • 策略模式造成很多的策略类,增加维护难度。

    3.策略设计模式的实现思路

    策略模式是准备一组算法,并将这组算法封装到一系列的策略类里面,作为一个抽象策略类的子类。策略模式的重心不是如何实现算法,而是如何组织这些算法,从而让程序结构更加灵活,具有更好的维护性和扩展性。

    策略设计模式涉及的角色:

    • 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。

    • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。

    • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

    4.代码示例

    /**
     * 折扣
     */
    public interface Discount {
        /**
         * 计算价格
         * @param money
         * @return
         */
        public int calculate(int money);
    }
    /**
     * 满减策略
     * 需要满200
     */
    public class FullDiscount implements Discount{
        @Override
        public int calculate(int money) {
            if (money>200){
                System.out.println("符合满减策略,进行满减");
                return money - 30;
            }
            return money;
        }
    }
    
    /**
     * 假日折扣
     * 需要大于100
     */
    public class HolidayDiscount implements Discount{
        @Override
        public int calculate(int money) {
            if (money > 100){
                return money - 10;
            }
            return money;
        }
    }
    
    
    /**
     * 新用户减免
     * 但是也需要大于100
     */
    public class NewerDiscount implements Discount{
        @Override
        public int calculate(int money) {
            if (money>100){
                return money-20;
            }
            return money;
        }
    }
    
    /**
     * 第二单8折优惠
     */
    public class SecondDiscount implements Discount {
        @Override
        public int calculate(int money) {
            Double balance =  money * 0.8;
            return balance.intValue();
        }
    }
    
     public static void main(String[] args) {
            List<Fruit> products = new ArrayList();
    
            products.add(StaticFactory.getFruitApple());
            products.add(StaticFactory.getFruitBanana());
            products.add(StaticFactory.getFruitOrange());
    
            ShoppingCart cart = new CartShopping(products);
    
            /*注入优惠方案*/
            cart.setDiscount(new FullDiscount());
    
            cart.submitOrder();
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    5.策略设计模式的应用场景

    在程序设计中,通常在以下几种情况中使用策略模式较多:

    1. 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
    2. 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
    3. 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
    4. 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
    5. 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。
  • 相关阅读:
    Pt/CeO2单原子纳米酶|H-rGO-Pt@Pd NPs纳米酶|碳纳米管负载铂颗粒纳米酶|白血病拮抗多肽修饰的FeOPtPEG复合纳米酶
    CSS padding(填充)
    微服务 Spring Boot 整合Redis 实现优惠卷秒杀 一人一单
    【浅学Java】排序大全
    SQL数据库性能优化
    C++ 获取网卡名称和IP地址
    一文带你了解RabbitMQ
    RK3568开发笔记(八):开发板烧写buildroot固件(支持hdmi屏),搭建Qt交叉编译开发环境,编译一个Demo,目标板运行Demo测试
    Netty入门——组件(Channel)一
    C语言变量、指针的内存关系
  • 原文地址:https://blog.csdn.net/u014078003/article/details/125909609