热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

设计模式之:策略模式

声明[版权申明]非商业目的注明出处可自由转载博

声明

[版权申明]非商业目的注明出处可自由转载
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/86644481
出自:shusheng007

前言

人在IT江湖飘,不懂设计模式咋装X?

我们这个社会上的事情大概率都符合八二法则,软件领域也一样。例如你学习一门编程语言,工作中常用的类来来回回也就那么几十个。那么多设计模式,最常被人使用的也就那么几种,所以我们在做事情的时候应该首先着眼于那20%。

策略模式算是设计模式中简单而又常用的了。

定义

策略模式定义了一系列的算法,并将每一个算法封装起来,使他们可以相互替换。

使用场景

当你写代码的时候发现一个操作有好多种实现方法,而你需要根据不同的情况使用if-else等分支结构来确定使用哪种实现方式的时候,想一想这个模式。

如何实现

业务场景

2017年的2月14号,王二狗和牛翠花约好在天津之眼约定终身,二狗打扮一番后准备出发,此时问题来了:是坐公交去呢,还是打滴滴快车呢?天气看起来也不错,要不骑共享单车吧,省钱还锻炼身体。

对应到编程领域就是:目前有三种策略可以实现一个特定的目的,使用何种策略取决于调用者(客户端)

普通实现

如果我们正常写代码,平时也应该这样,首先保证把功能正确的实现了,然后慢慢重构,设计模式都是在不断的重构当中应用的。 王二狗会调用会调用goToTianJinEye()方法,根据自己的实际情况,选择某一种出行方式。

public class TrafficFeeCalculator {
public int goToTianJinEye(String way, int distance) {
int trafficFee = 0;
switch (way) {
case "bus":
if (distance < 10)
trafficFee = 4;
else
trafficFee = 6;
break;
case "didi":
if(distance<3)
trafficFee = 8;
else
trafficFee=8+(distance-3)*3;
break;
case "sharedBicyle":
trafficFee = 2;
break;
default:
break;
}
return trafficFee;
}
}

那么这么写有什么弊端呢?

  • 第一:每一种出行方式的交通花费的计算方式都写在了TrafficFeeCalculator类中,这个类承担的职责较多,违反了单一职责原则。

  • 第二:假如王二狗突然想自己开车去,那就需要修改goToTianJinEye这个方法了。违反了开闭原则。

使用策略模式

以上的场景非常适合使用策略模式,将多种不同的实现算法封装,然后客户端根据不同策略分别调用相应的算法。

20190303114047324

第一步:封装不同的实现算法
首先定义一个策略接口,规定算法的同一操作

public interface CalculateStrategy {
int calculateTrafficFee(int distance);
}

第二步:封装各个算法

//乘坐公交车算法
public class ByBus implements CalculateStrategy {
@Override
public int calculateTrafficFee(int distance) {
return distance<10?4:6;
}
}
//乘坐滴滴快车算法
public class ByDiDiExpress implements CalculateStrategy {
@Override
public int calculateTrafficFee(int distance) {
return distance<3?8:(8+(distance-3)*3);
}
}
//骑共享单车算法
public class BySharedBicycle implements CalculateStrategy {
@Override
public int calculateTrafficFee(int distance) {
return 2;
}
}

第三步:使用算法

public class TrafficFeeCalculator {
...
public int goToTianJinEye(CalculateStrategy strategy,int distance){
return strategy.calculateTrafficFee(distance);
}
}

第四步:客户端调用
根据情况,构建相应的算法类实例,传入计算器计算即可

public static void main(String[] args) {
TrafficFeeCalculator calculator=new TrafficFeeCalculator();
System.out.println(String.format("乘坐公交车到天津之眼的花费为:%d块人民币",
calculator.goToTianJinEye(new ByBus(),10)));
System.out.println(String.format("乘坐滴滴快车到天津之眼的花费为:%d块人民币",
calculator.goToTianJinEye(new ByDiDiExpress(),10)));
System.out.println(String.format("骑共享单车到天津之眼的花费为:%d块人民币",
calculator.goToTianJinEye(new BySharedBicycle(),10)));
}

输出为:

乘坐公交车到天津之眼的花费为:6块人民币
乘坐滴滴快车到天津之眼的花费为:29块人民币
骑共享单车到天津之眼的花费为:2块人民币

二狗为了早点见到自己心爱的牛翠花,最终选择了滴滴快车,贵是贵了点,但是快!

优缺点

  • 优点:降低了算法类的职责,使各个算法可以独立变化并互相替换。而且使得增加新的算法变的很容易,降低了对原有系统的侵入,最终使得程序可扩展可维护性增强。

  • 缺点:所有设计模式的通病,类增多了,程序从局部来看变的更复杂了。

总结

是不是感觉讲设计模式的文章都有一个特点,使用了设计模式反而比不使用设计模式使程序看起来更加复杂,而不是更加简单。那是因为每篇文章的示例都是无实际使用意义的示例代码,实际情况是程序非常复杂才需要使用到设计模式。一个大型程序是不断迭代出来的,一开始肯定不长那样,程序员日常接到一个开发任务也不要过多的想,这个我应该用个什么设计模式呀?先把功能实现了,然后回头看看有没有遵循面向对象编程6大原则,如果没有想想怎么改进,然后设计模式就登场了。。。


版权声明:本文为wuxiaolongah原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/wuxiaolongah/article/details/123054744
推荐阅读
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • 本文介绍了Oracle存储过程的基本语法和写法示例,同时还介绍了已命名的系统异常的产生原因。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
author-avatar
爱吃肉肉的狼
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有