深入理解Java设计模式之策略模式

 更新时间:2021年11月07日 15:50:00   作者:一指流砂~  
这篇文章主要介绍了JAVA设计模式之策略模式的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下

一、什么是策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。

策略模式定义和封装了一系列的算法,它们是可以相互替换的,也就是说它们具有共性,而它们的共性就体现在策略接口的行为上,另外为了达到最后一句话的目的,也就是说让算法独立于使用它的客户而独立变化,我们需要让客户端依赖于策略接口。

一种很简单的解释,在我们的开发过程中,经常会遇到大量的if...else或者switch...case语句,当这些语句在开发中只是为了起到分流作用,这些分流和业务逻辑无关,那么这个时候就可以考虑用策略模式。

二、策略模式的结构

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

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

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

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

三、策略模式的应用场景

举一个例子,商场搞促销--打8折,满200送50,满1000送礼物,这种促销就是策略。

再举一个例子,dota里面的战术,玩命四保一,三伪核体系,推进体系,大招流体系等,这些战术都是一种策略。

应用场景:

1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。

2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。

3、 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

四、策略模式的优缺点

优点:

1、结构清晰,把策略分离成一个个单独的类「替换了传统的 if else」2、代码耦合度降低,安全性提高「各个策略的细节被屏蔽」

缺点:

1、客户端必须要知道所有的策略类,否则你不知道该使用那个策略,所以策略模式适用于提前知道所有策略的情况下2、策略类数量增多(每一个策略类复用性很小,如果需要增加算法,就只能新增类)五、策略模式和简单工厂模式的异同

在上篇文章已经提过了,传送地址:深入理解设计模式(二):简单工厂模式

六、策略模式的实现

Strategy类,定义所有支持的算法的公共接口

//Strategy类,定义所有支持的算法的公共接口
abstract class Strategy
{
    //算法方法
    public abstract void AlgorithmInterface();
}

oncreteStrategy,封装了具体的算法或行为,继承于Strategy

//算法A
    class ConcreteStrategyA : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("算法A的实现");
        }
    }
    //算法B
    class ConcreteStrategyB : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("算法B的实现");
        }
    }
    //算法C
    class ConcreteStrategyC : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine("算法C的实现");
        }
    }

Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用

//Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用
    class Context
    {
        Strategy Strategy;
        public Context(Strategy Strategy)
        {
            this.Strategy = Strategy;
        }
        //上下文接口
        public void ContextInterface()
        {
            Strategy.AlgorithmInterface();
        }
    }

客户端代码

static void Main(string[] args)
        {
            Context Context;

            Context = new Context(new ConcreteStrategyA());
            Context.ContextInterface();

            Context = new Context(new ConcreteStrategyB());
            Context.ContextInterface();

            Context = new Context(new ConcreteStrategyC());
            Context.ContextInterface();

            Console.Read();
        }

七、策略模式和简单工厂模式的结合

改造后的Context

class Context
    {
        Strategy Strategy=null;
        public Context(string type)
        {
            switch (type)
            {
                case "A":
                    ConcreteStrategyA A = new ConcreteStrategyA();
                    Strategy = A;
                    break;
                case "B":
                    ConcreteStrategyB B = new ConcreteStrategyB();
                    Strategy = B;
                    break;
                case "C":
                    ConcreteStrategyC C = new ConcreteStrategyC();
                    Strategy = C;
                    break;
            }
        }
        //上下文接口
        public void ContextInterface()
        {
            Strategy.AlgorithmInterface();
        }
    }

改造后的客户端代码

static void Main(string[] args)
        {
            Context Context = new Context("这里是相应的算法类型字符串");
            Context.ContextInterface();

            Console.Read();
        }

对比下改造前后的区别不难看出,改造前客户端需要认识两个类,Context和ConcreteStrategy。而策略模式和简单工厂模式结合后,客户端只需要认识一个类Context,降低了耦合性。

八、策略枚举的实现

我们可以使用枚举在一个类中实现以上所有的功能及三种不同的角色,下面看看怎么通过枚举来实现策略模式

public enum Calculator 
{    ADD("+") {        
        public int exec(int a, int b) {    
            return a+b;        
        }
    },        
    SUB("-") {        
        public int exec(int a, int b) {        
            return a-b;        
            }    
    };            
    public abstract int exec(int a, int b);        
    //运算符    
    private String value = "";        
    private Calculator(String value)
    {        
        this.value = value;
    }     
    public String getValue() 
    {        
        return value;
    }
}

在枚举类中,定义的抽象方法就像当时之前的接口,每一个枚举ADD SUB相当是一个具体的实现类(策略角色),而整个枚举类就是策略的分装角色。

这是从网上copy的代码,本人不怎么喜欢这么写,总感觉违背了代码规范。

九、总结

策略模式,实质就是封装了一些算法,让算法可以互相替换,用户可以自由选择这些算法进行操作。策略模式本身理解起来没什么难点,但是在实际应用中其本身主要结合工厂模式一起使用。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • idea常用配置之注释快捷键方式

    idea常用配置之注释快捷键方式

    这篇文章主要介绍了idea常用配置之注释快捷键方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • java 出现Zipexception 异常的解决办法

    java 出现Zipexception 异常的解决办法

    这篇文章主要介绍了java 出现Zipexception 异常的解决办法的相关资料,出现 java.util.zip.ZipException: error in opening zip file 异常的原因及解决方法,需要的朋友可以参考下
    2017-08-08
  • tomcat请求流程源码解进阶篇

    tomcat请求流程源码解进阶篇

    这篇文章主要为大家介绍了tomcat请求流程源码解进阶,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • SpringBoot项目中的favicon.ico图标无法显示问题及解决

    SpringBoot项目中的favicon.ico图标无法显示问题及解决

    这篇文章主要介绍了SpringBoot项目中的favicon.ico图标无法显示问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • spring的IoC和DI详解

    spring的IoC和DI详解

    这篇文章主要介绍了spring的IoC和DI详解,还是挺不错的,这里分享给加,需要的朋友可以参考下。
    2017-11-11
  • 微信开发之使用java获取签名signature

    微信开发之使用java获取签名signature

    这篇文章主要为大家详细介绍了微信开发之使用java获取签名signature,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Spring Cloud整合XXL-Job的示例代码

    Spring Cloud整合XXL-Job的示例代码

    这篇文章主要介绍了springcloud整合xxl-job的示例代码,主要分为四个过程,本文给大家介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • Java实现顺序表和链表结构

    Java实现顺序表和链表结构

    大家好,本篇文章主要讲的是Java实现顺序表和链表结构,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • Java实现文件批量重命名具体实例

    Java实现文件批量重命名具体实例

    这篇文章主要介绍了Java实现文件批量重命名具体实例,需要的朋友可以参考下
    2014-02-02
  • SpringBoot开发教程之AOP日志处理

    SpringBoot开发教程之AOP日志处理

    现在凡是企业级的或者稍微大点项目,基本都需要日志管理,下面这篇文章主要给大家介绍了关于SpringBoot开发教程之AOP日志处理 的相关资料,需要的朋友可以参考下
    2021-10-10

最新评论