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、需要安全地封装同一类型的操作。

  • 相关阅读:
    天天生鲜项目需求分析——基于Django框架的天天生鲜电商网站项目系列博客(一)
    预训练模型专题_GPT2_模型代码学习笔记
    Logistic模型原理详解以及Python项目实现
    【人生苦短,我学 Python】基础篇——基本语句(Day5)
    “TensorFlow 开发者出道计划”全攻略,玩转社区看这里!
    程序员常用的六大技术博客类
    [慕课笔记]Node入口文件分析和目录初始化
    如何在面试中脱颖而出?
    程序媛,坚持这几个好习惯让你越来越美
    2017前端精品面试文章总结
  • 原文地址:https://www.cnblogs.com/sench/p/8877038.html
Copyright © 2011-2022 走看看