Java设计模式(十三)之行为型模式:策略模式

Java设计模式(十三)之行为型模式:策略模式

一、背景:

在软件开发中常常遇到这种情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找、排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…或者case等条件判断语句来进行选择。

这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。如果我们将这些策略包含在客户端,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。

如何让算法和对象分开来,使得算法可以独立于使用它的客户而变化?

解决方法:就是使用策略模式。

 

二、策略模式定义:

把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。

比如定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换,使得算法可独立于使用它的客户而变化。这就是策略模式。

UML结构图:

Java设计模式(十三)之行为型模式:策略模式

组成:
(1)环境类(Context):用一个ConcreteStrategy对象来配置。持有Strategy对象并维护对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。

(2)抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。

(3)具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法。

 

三、代码实现:

场景如下,刘备要到江东娶老婆了,走之前诸葛亮给赵云三个锦囊妙计,说是按天机拆开能解决棘手问题。场景中出现三个要素:三个妙计(具体策略类)、一个锦囊(环境类)、赵云(调用者)。

抽象策略类(Strategy):

public interface Strategy {
     public void operate();
}

三个实现类(ConcreteStrategy):

//妙计一:初到吴国
public class BackDoor implements IStrategy {
     @Override
     public void operate() {
          System.out.println("找乔国老帮忙,让吴国太给孙权施加压力,使孙权不能杀刘备");
     }
}

//求吴国太开绿灯放行
public class GivenGreenLight implements IStrategy {
     @Override
     public void operate() {
          System.out.println("求吴国太开个绿灯,放行");
     }
}

//孙夫人断后,挡住追兵
public class BlackEnemy implements IStrategy {
     @Override
     public void operate() {
          System.out.println("孙夫人断后,挡住追兵");
     }
}

环境类(Context):

public class Context {
     private Strategy strategy;
     //构造函数,要你使用哪个妙计
     public Context(Strategy strategy){
          this.strategy = strategy;
     }
     public void setStrategy(Strategy strategy){
          this.strategy = strategy;
     }
     public void operate(){
          this.strategy.operate();
     }
}

下面就是使用的情况了:

public class Zhaoyun {
 
public static void main(String[] args) {
     Context context;
 
     System.out.println("----------刚到吴国使用第一个锦囊---------------");
     context = new Context(new BackDoor());
     context.operate();
     System.out.println("\n");
 
     System.out.println("----------刘备乐不思蜀使用第二个锦囊---------------");
     context.setStrategy(new GivenGreenLight());
     context.operate();
     System.out.println("\n");
 
     System.out.println("----------孙权的追兵来了,使用第三个锦囊---------------");
     context.setStrategy(new BlackEnemy());
     context.operate();
     System.out.println("\n");
     }
}

三招下来,搞得的周郎是“赔了夫人又折兵”。

以上就是策略模式,多种不同解决方案动态切换,起到改变对象行为的效果。

 

四、小结:

1、优点:

(1)可以动态改变对象的行为;

2、缺点:

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

(2)策略模式将产生很多策略类。

3、适用场景:

(1)许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态地在几种算法中选择一种。

(2)当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。

(3)一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
 

原博客链接:

https://blog.csdn.net/jason0539/article/details/45007553

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100063.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 分区容错性和可用性的区别

    分区容错性和可用性的区别分区容错性:因为网络等硬件引起的问题,一台服务器崩溃了,保证能在其他服务器上也能顺利完成业务。可用性:因为软件代码层面的问题,一台服务器上的服务崩溃了,保证能在其他服务器上完成该业务。区别:分区容错性更偏向于硬件引起的问题可用性更偏向于软件代码层面的问题…

  • OFFSet_offtheroad

    OFFSet_offtheroad#defineoffsetof(s,m)(size_t)&reinterpret_cast<constvolatilechar&>((((s*)0)->m))该宏用于求结构体中一个成员在该结构体中的偏移量。第一个参数是结构体的名字,第二个参数是结构体成员的名字。该宏返回结构体structNames中成员memberName(m)的偏移量。偏移量…

  • 什么是虚拟IP_虚拟机IP

    什么是虚拟IP_虚拟机IP【导读】虚拟ip和真实ip区别,下面就是191路由网整理的网络知识百科,来看看吧!大家好,我是191路由器网小编,上述问题将由我为大家讲解。虚拟ip和真实ip区别是真实IP是网络运营商提供的所以不能自己变更,虚拟IP是自己设置的可以变更。虚拟IP,就是一个未分配给真实主机的IP。也就是说对外提供服务器的主机除了有一个真实IP外还有一个虚拟IP,使用这两个IP中的任意一个都可以连接到这台主机。互联网…

    2022年10月20日
  • mysql 主键自增语句_MySQL 自增主键[通俗易懂]

    mysql 主键自增语句_MySQL 自增主键[通俗易懂]以下仅考虑InnoDB存储引擎。自增主键有两个性质需要考虑:单调性每次插入一条数据,其ID都是比上一条插入的数据的ID大,就算上一条数据被删除。连续性插入成功时,其数据的ID和前一次插入成功时数据的ID相邻。自增主键的单调性为何会有单调性的问题?这主要跟自增主键最大值的获取方式,以及存放位置有关系。如果最大值是通过计算获取的,并且在某些情况下需要重新获取时,会因为最新的数据被删…

  • Python数组的使用_算法高效性

    Python数组的使用_算法高效性如果我们需要一个只包含数字的列表,那么使用数组方式比list方式更高效。而且数组还支持所有跟可变序列有关的操作,比如移除列表中的一个元素(.pop)、插入元素(.insert)和在列表末尾一次性追加另一个序列中的多个值(.extend)。除此之外,数组还定义从文件读取(.frombytes)与写入(.tofile)的效率更高的方法。创建数组需要一个类型码,形如array(‘d’),这个类型码是用来表示在底层实现的C语言的数据类型。一般我们用的Python底层是用C语言编写实现的&n

  • C#文件流FileStream的用法[通俗易懂]

    C#文件流FileStream的用法[通俗易懂]1、简介FileStream类:主要用于对文件进行读取、写入、打开和关闭操作,并对其他与文件相关的操作系统句柄进行操作,如管道、标准输入和标准输出。读写操作可以指定为同步或异步操作。FileStream对输入输出进行缓冲,从而提高性能。——MSDN**简单点说:FileStream类可以对任意类型的文件进行读取操作,可根据需要来指定每次读取的字节长度(这是比File类优秀的地方之一),…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号