• java设计模式--策略模式


    策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

    本文地址:http://www.cnblogs.com/wuyudong/p/5924223.html,转载请注明源地址。

    策略模式的结构

      策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。下面就以一个示意性的实现讲解策略模式实例的结构。

    这个模式涉及到三个角色:

      ● 环境(Context)角色:持有一个Strategy的引用。

      ● 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

      ● 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

    策略模式的使用场景:

    1)针对同一种问题的多种处理方式、仅仅是因为具体行为有差别时,

    2)需要安全的封装多种同一类型的操作时

    3)出现同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时。

    策略模式的实现

    举个例子,计算公交车和地铁运行指定路程后所需的票价

    package com.wuyudong.strategy.normal;
    
    public class PriceCalculator {
        // 公交车类型
        private static final int BUS = 1;
        // 地铁类型
        private static final int SUBWAY = 2;
    
        public static void main(String[] args) {
            PriceCalculator calculator = new PriceCalculator();
            System.out.println("坐10公里的公交车的票价为:"
                    + calculator.calculatePrice(10, BUS));
            System.out.println("坐10公里的地铁的票价为:"
                    + calculator.calculatePrice(10, SUBWAY));
    
        }
        
        //计算公交价格
        private int busPrice(int km) {
            int extraTotal = km - 10;
            int extraFactor = extraTotal / 5;
            int fraction = extraTotal % 5;
            int price = 1 + extraFactor * 1;
            return fraction > 0 ? ++price : price;
        }
    
        //计算地铁价格
        private int subwayPrice(int km) {
            if (km <= 6) {
                return 3;
            } else if (km > 6 && km < 12) {
                return 4;
            } else if (km < 22 && km > 12) {
                return 5;
            } else if (km < 32 && km > 22) {
                return 6;
            }
            return 7;
        }
    
        //根据类型来计算相应的价格
        private int calculatePrice(int km, int type) {
            if (type == BUS) {
                return busPrice(km);
            } else {
                return subwayPrice(km);
            }
        }
    }

    如果再添加一种出租车的价格计算,添加相应的代码:

    public class PriceCalculator {
        // 公交车类型
        private static final int BUS = 1;
        // 地铁类型
        private static final int SUBWAY = 2;
    
        // 出租车类型
        private static final int TAXI = 3;
    
        public static void main(String[] args) {
            PriceCalculator calculator = new PriceCalculator();
            System.out.println("坐10公里的公交车的票价为:"
                    + calculator.calculatePrice(10, BUS));
            System.out.println("坐10公里的地铁的票价为:"
                    + calculator.calculatePrice(10, SUBWAY));
    
        }
    
        // 计算出租车价格
        private int taxiprice(int km) {
            return km * 2;
        }
    
        // 根据类型来计算相应的价格
        private int calculatePrice(int km, int type) {
            if (type == BUS) {
                return busPrice(km);
            } else if (type == SUBWAY) {
                return subwayPrice(km);
            } else {
                return taxiprice(km);
            }
        }
    }

    可见上面的代码耦合性较高,每当增加新的交通工具类型的时候,需要不断的修改大量的代码,这里使用策略模式重构:

    首先定义一个抽象的价格计算接口:

    //计算接口
    public interface CalculateStrategy {
        int calculatePrice(int km);
    }

    每一种出行方式都定义一个独立的计算策略类:

    公交车计算策略

    public class BusStrategy implements CalculateStrategy {
        public int calculatePrice(int km) {
            int extraTotal = km - 10;
            int extraFactor = extraTotal / 5;
            int fraction = extraTotal % 5;
            int price = 1 + extraFactor * 1;
            return fraction > 0 ? ++price : price;
        }
    
    }

    地铁计算策略

    public class SubwayStrategy implements CalculateStrategy {
    
        public int calculatePrice(int km) {
            if (km <= 6) {
                return 3;
            } else if (km > 6 && km < 12) {
                return 4;
            } else if (km < 22 && km > 12) {
                return 5;
            } else if (km < 32 && km > 22) {
                return 6;
            }
            return 7;
        }
    }

    再创建一个扮演Context的角色,代码如下:

    public class TranficCalculator {
        CalculateStrategy mStrategy;
        
        public static void main(String[] args) {
            TranficCalculator calculator = new TranficCalculator();
            //设置计算策略
            calculator.setStrategy(new BusStrategy());
            //计算价格
            System.out.println("公交车乘10公里的价格:" + calculator.calculatePrice(10));
            
        }
        
        public void setStrategy(CalculateStrategy mStrategy) {
            this.mStrategy = mStrategy;
        }
        public int calculatePrice(int km) {
            return mStrategy.calculatePrice(km);
        }
    }

    这样即使需要添加出租车的价格计算,只需要简单的新建一个类,让其继承自CalculateStrategy接口并实现其中的方法即可

    优点

    1)结构清晰明了、使用简单直观

    2)耦合度相对较低,扩展方便

    3)操作封装因为更为测地、数据更为安全

    缺点

    子类增多

  • 相关阅读:
    excel导出的时候从程序后台写到excel里的是文本,所以无法在excel中计算怎么办?
    深度经验总结:快逸报表工具单数据集版本和多数据集版本的主要区别之一
    如何循序渐进有效学习 JavaScript?
    MariaDB和mySQL到底区别在哪,实验说明问题!
    实现点击页面报表头某个字段进行该字段的重新排序: 经过验证,此代码是工作的
    Oracle TDE的学习
    LOB类型的学习、总结
    使用GC 初始化DG(将备份集复制到目标端再初始化)
    oradebug 的学习 一
    角色 RESOURCE、CONNECT、DBA具有的权限
  • 原文地址:https://www.cnblogs.com/wuyudong/p/5924223.html
Copyright © 2020-2023  润新知