zoukankan      html  css  js  c++  java
  • 策略模式

    有道无术,术可求
    有术无道,止于术

    一、策略模式的定义

    先举一个例子来说:在网上购物的时候,有的时候会有一些打折的活动,可能会给你5元的优惠券,也有可能会给一张满减的优惠券,而无论给怎样的优惠券,到了开发人员的那边,这不过是它们写好的一些或者是封装好的一些类,这些这都是可以随时替换的,想搞一个其它的活动,就把它们替换成其它的类,当然,这只是举一个例子,实际的代码实现是很复杂的。

    策略的定义,定义了很多的算法,将它们分别的封装了起来,它们之间可以互相的替换

    在策略模式中,写好的算法是和我们操作的对象是会分开的,可以看下写好的策略模式的UML:

    策略模式UML

    在上面的UML中可以看到算法和对象的本身之间是区分开来的,所以这里是分成了三个部分:

    • 环境(Context):可以来操作策略
    • 抽象策略(Strategy):这里面定义了具体策略要实现的方法
    • 具体策略(ConcreteStrategy):实现了Strategy,将Strategy里面的方法都实现

    二、策略模式的应用场景

    • 系统中有很多的类,这些类的区别只是在具体的代码实现上不一至
    • 其中有的系统可能会有多种算法,通过策略模式可以在这些类中任意选择

    优点:

    • 可以在不修改原有系统的情况下,选择具体的行为
    • 可以大量的消除条件语句,if....else switch
    • 可以降低代码的耦合

    缺点:

    • 在使用的时候客户端要知道有那些类
    • 可能会发生类爆炸

    三、策略模式的代码实现

    定义Strategy
    这个是我们上面所说的抽象策略,里面是具体策略要实现的方法,它是一个接口

    public interface BreadIngredients {
        public void addIngredients();
    }
    

    定义ConcreteStrategy
    在这个里面我们有了具体的实现,里面就是我们要实现的一些算法,这个类可以有多个,但是要实现Strategy接口

    public class NiuRouIngredients implements BreadIngredients {
        @Override
        public void addIngredients() {
            System.out.println("添加了牛肉的配料");
        }
    }
    
    public class SaLaIngredients implements BreadIngredients {
        @Override
        public void addIngredients() {
            System.out.println("添加了沙拉的配料");
        }
    }
    

    定义Context
    这个里面我们要操作策略类
    可以看出这个在这个类中聚合了BreadIngredients,只要传入一个BreadIngredients的子类就可以了

    public class BreadFactory  {
    
        private BreadIngredients breadIngredients;
    
        public BreadFactory(BreadIngredients breadIngredients){
            this.breadIngredients = breadIngredients;
        }
    
        public void ProcessingBread(){
            breadIngredients.addIngredients();
        }
    }
    

    这个是一个客户端类,我们在这个类里面进行测试

    public class Client {
        public static void main(String[] args) {
            BreadFactory niuRoubread = new BreadFactory(new NiuRouIngredients());
            BreadFactory saLabread = new BreadFactory(new SaLaIngredients());
    
            niuRoubread.ProcessingBread();
            saLabread.ProcessingBread();
        }
    }
    

    通过上面的代码大概对策略模式有了相应的了解,就是说在处理一些问题的时候可能会有好多的解法,只要选择了里面的一种就可以了。

    四、使用策略模式和工厂模式混合使用

    在有的时候,写代码的过程中使用了策略模式还是避免不了有很多的if....else,为了避免这种冗余的代码,这使用工厂模式和策略模式的情况下可以避免这种情况

    创建一个空的具体抽象策略

    public class NONELngredients implements BreadIngredients{
        @Override
        public void addIngredients() {
            System.out.println("没有此项");
        }
    }
    

    这里我就创建一个工厂类

    public class BreadFactoryAndCeLue {
        //这个MAP要保存用的策略模式的类
        private static Map<String,BreadIngredients> MAP_BREAD = new HashMap<String,BreadIngredients>();
        //因为在下面的静态方法中,如果找不到Map中的数据,就会返回一个空的类
        private static BreadIngredients NONE = new NONELngredients();
        static {
            MAP_BREAD.put(Map_Key.niurou,new NiuRouIngredients());
            MAP_BREAD.put(Map_Key.sala,new SaLaIngredients());
        }
        //因为这个是工厂类,所以私有化构造方法
        private BreadFactoryAndCeLue(){}
    
        public static BreadIngredients getBreadIngredients(String key){
            BreadIngredients breadIngredients = MAP_BREAD.get(key);
            return breadIngredients == null ? NONE : breadIngredients;
        }
    
        public interface Map_Key{
            public String niurou = "niurou";
            public String sala = "sala";
        }
    }
    

    可以看出在下面的测试的方法里面,if...else减少了
    测试方法

        public static void main(String[] args) {
            String key = "niurou";
            BreadIngredients breadIngredients = BreadFactoryAndCeLue.getBreadIngredients(key);
            breadIngredients.addIngredients();
        }
    

    结果

    注:在使用策略模式的时候,如果类有很多,就要考滤可不可以使用策略模式结合其它的模式配合使用

  • 相关阅读:
    Odoo search 搜索视图详解与搜索视图工作原理
    Odoo treeView列表视图详解
    Odoo视图的共有标签
    Odoo中的字段显示方式和行为控制
    Odoo中的env详解
    Odoo中报表PDF样式出错的解决办法
    odoo Botton标签属性详解
    Odoo甘特图
    Odoo field字段标签属性详解
    Odoo form视图详解
  • 原文地址:https://www.cnblogs.com/sdayup/p/13231259.html
Copyright © 2011-2022 走看看