深入理解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的代码,本人不怎么喜欢这么写,总感觉违背了代码规范。

九、总结

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

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

相关文章

  • Graceful Response 构建 Spring Boot 响应处理的方法

    Graceful Response 构建 Spring Boot 响应

    Graceful Response是一个Spring Boot技术栈下的优雅响应处理器,提供一站式统一返回值封装、全局异常处理、自定义异常错误码等功能,本文介绍Graceful Response 构建 Spring Boot 下优雅的响应处理,感兴趣的朋友一起看看吧
    2024-01-01
  • SpringBoot项目速度提升之延迟初始化(Lazy Initialization)详解

    SpringBoot项目速度提升之延迟初始化(Lazy Initialization)详解

    延迟初始化(Lazy Initialization)是一种在需要时才创建或加载对象的策略,以减少启动时间和资源消耗,本文就来讲讲延迟初始化的具体使用吧
    2023-05-05
  • Struts2单选按钮详解及枚举类型的转换代码示例

    Struts2单选按钮详解及枚举类型的转换代码示例

    这篇文章主要介绍了Struts2单选按钮详解及枚举类型的转换代码示例,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Java实现按照大小写字母顺序排序的方法

    Java实现按照大小写字母顺序排序的方法

    这篇文章主要介绍了Java实现按照大小写字母顺序排序的方法,涉及java数组遍历、编码转换、判断等相关操作技巧,需要的朋友可以参考下
    2017-12-12
  • SpringMVC源码解析之消息转换器HttpMessageConverter

    SpringMVC源码解析之消息转换器HttpMessageConverter

    本篇文章主要介绍了SpringMVC源码解析之消息转换器HttpMessageConverter ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Java中关于二叉树的概念以及搜索二叉树详解

    Java中关于二叉树的概念以及搜索二叉树详解

    二叉树是一种很有用的非线性结构,日常的开发中常会用到,关于二叉树的概念以及搜索二叉树本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • SpringCloud项目中Feign组件添加请求头所遇到的坑及解决

    SpringCloud项目中Feign组件添加请求头所遇到的坑及解决

    这篇文章主要介绍了SpringCloud项目中Feign组件添加请求头所遇到的坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Java并发之BlockingQueue的使用

    Java并发之BlockingQueue的使用

    这篇文章主要介绍了Java并发之BlockingQueue的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • springcloud feign传输List的坑及解决

    springcloud feign传输List的坑及解决

    这篇文章主要介绍了springcloud feign传输List的坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • JDK安装配置教程

    JDK安装配置教程

    这篇文章主要为大家详细介绍了JDK安装配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01

最新评论