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

九、总结

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

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

相关文章

  • java实现可安装的exe程序实例详解

    java实现可安装的exe程序实例详解

    这篇文章主要介绍了java实现可安装的exe程序实例详解的相关资料,通过此文希望能帮助到大家,让大家实现这样的功能,需要的朋友可以参考下
    2017-10-10
  • SpringBoot整合Netty的流程步骤

    SpringBoot整合Netty的流程步骤

    Netty是一个基于Java的开源网络应用框架,它提供了高性能、异步事件驱动的网络编程能力,Netty旨在帮助开发者构建高性能、高可靠性的网络应用程序,本文给大家详细介绍了SpringBoot整合Netty的流程步骤,需要的朋友可以参考下
    2023-09-09
  • 初次使用IDEA创建maven项目的教程

    初次使用IDEA创建maven项目的教程

    这篇文章主要介绍了初次使用IDEA创建maven项目的教程讲解,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Java 高并发九:锁的优化和注意事项详解

    Java 高并发九:锁的优化和注意事项详解

    本文主要介绍Java高并发锁的优化和注意事项,这里整理了详细的资料,并讲解了 1. 锁优化的思路和方法 2. 虚拟机内的锁优化 3. 一个错误使用锁的案例 4. ThreadLocal及其源码分析等知识,有需要的小伙伴可以参考下
    2016-09-09
  • Java设计模式以虹猫蓝兔的故事讲解装饰器模式

    Java设计模式以虹猫蓝兔的故事讲解装饰器模式

    装饰器模式又名包装(Wrapper)模式。装饰器模式以对客户端透明的方式拓展对象的功能,是继承关系的一种替代方案,本篇文章以虹猫蓝兔生动形象的为你带来详细讲解
    2022-04-04
  • 浅谈spring-boot的单元测试中,@Before不被执行的原因

    浅谈spring-boot的单元测试中,@Before不被执行的原因

    这篇文章主要介绍了浅谈spring-boot的单元测试中,@Before不被执行的原因,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • java布局管理之CardLayout简单实例

    java布局管理之CardLayout简单实例

    这篇文章主要为大家详细介绍了java布局管理之CardLayout的简单实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Spring中的AOP原理与使用详解

    Spring中的AOP原理与使用详解

    这篇文章主要介绍了Spring中的AOP原理与使用详解,AOP意为面向切面编程,可以通过预编译方式或运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术,需要的朋友可以参考下
    2023-12-12
  • 一名Java高级工程师需要学什么?

    一名Java高级工程师需要学什么?

    作为一名Java高级工程师需要学什么?如何成为一名合格的工程师,这篇文章给了你较为详细的答案,需要的朋友可以参考下
    2017-08-08
  • Servlet简单实现登录功能

    Servlet简单实现登录功能

    这篇文章主要为大家详细介绍了Servlet简单实现登录功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03

最新评论