zoukankan      html  css  js  c++  java
  • 设计模式(一) 策略模式

    一、模式动机

    为什么要使用策略模式呢?在日常开发中,我们可以发现一种需求可以有不同的方法来实现,比如我们要对一个数组进行排序,就可以使用多种不同的排序方法(选择排序、冒泡排序、快速排序等),每一种排序方法都可以被称作一种策略,我们可以在不同的情况下来选择不同的策略进行排序。在实现的时候我们可能会写一个算法类,包含了所有的排序算法,接着在我们需要排序的类(简称客户端)中创建算法类的对象,然后写一大段if...else来选择对象类中不同的排序算法。这种实现方式比较容易想到,但如果我们要增加一种新的排序算法,那么需要修改两个类:算法类和客户端,扩展和维护起来非常麻烦。为了解决这个问题,我们可以将每一个排序算法封装在一个独立的类中,这样一个独立的类我们称之为一种策略,为了保证这些策略的一致性,我们要建立一个抽象策略类,让包含排序算法的具体策略类实现抽象策略类。

    二、模式定义

    策略模式定义了算法族,并将这些算法封装起来成为类,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

    三、模式结构

    策略模式涉及到3个角色:

    1、Context:环境类(上下文类),持有一个Strategy的引用,负责调用相关算法;

    2、Strategy:抽象策略类,通常由接口或抽象类实现;

    3、ConcreteStrategy:具体策略类,实现了抽象策略类。

    这3种角色的代码可以用以下方式实现:

    抽象策略类Strategy:

    public interface Strategy{
        /**
         * 策略中包含的算法
         */
        void algorithm();
    }

    具体策略类ConcreteStrategy:

    具体策略类实现了抽象策略类:

    public class ConcreteStrategyA implements Strategy{
        @Override
        public void algorithm(){
            //具体算法或行为
        }
    }
    public class ConcreteStrategyB implements Strategy{
        @Override
        public void algorithm(){
            //具体算法或行为
        }
    }

    环境类Context:

    public class Context{
        //持有一个Strategy对象
        private Strategy strategy;
    
        //在构造函数中传入Strategy对象
        public Context(Strategy strategy){
            this.strategy = strategy;
        }
    
        //调用策略类中的算法
        public void contextInterface(){
            //if...else可以转移到这里
            strategy.algorithm();
        }
    
    }

    可以在客户端Client类中进行测试:

    public class Client{
        public static void main(String[] args){
            ConcreteStrategyA csa = new ConcreteStrategyA();
            Context context = new Context(csa);
            context.contextInterface();
        }
    }

    可以看到,在环境类Context中持有一个抽象的Strategy对象,而不是某一个具体的策略类,这样利用多态特性,当有新的排序算法时,我们只需要实现Strategy接口,而不用去修改客户端,也就是针对接口编程,而不是针对实现编程。通过策略模式,算法的使用和算法的实现被分离开来。

    四、优缺点

    优点:

    1、策略类易于扩展和维护;

    2、使用策略模式可以避免使用多重条件转移语句

    缺点:

    1、客户端必须实现知道所有的策略类,并自行决定使用哪一个策略类;

    2、在策略模式中将每一种算法都封装成一个策略类,这样会造成策略类过多,维护起来会带来额外开销。

    五、适用场景

    1、系统中的类主要逻辑相同,只是部分逻辑的实现方法不同,这样使用策略模式就可以动态的选择不同的行为;

    2、需要安全地封装同一类型的操作。

  • 相关阅读:
    苹果开发者账号注册申请(二)
    css3 media媒体查询器用法总结
    CSS,font-family,好看常用的中文字体
    行内元素和块级元素
    苹果开发者账号注册申请(一)
    web前端利用leaflet生成粒子风场,类似windy
    激光雷达--看图
    linux screen 多任务后台执行
    linux 系统监控和进程管理
    linux下postgresql的连接数配置
  • 原文地址:https://www.cnblogs.com/sench/p/8877038.html
Copyright © 2011-2022 走看看