热门标签 | 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
推荐阅读
  • 本文深入探讨了SQL数据库中常见的面试问题,包括如何获取自增字段的当前值、防止SQL注入的方法、游标的作用与使用、索引的形式及其优缺点,以及事务和存储过程的概念。通过详细的解答和示例,帮助读者更好地理解和应对这些技术问题。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 本文将详细探讨 Java 中提供的不可变集合(如 `Collections.unmodifiableXXX`)和同步集合(如 `Collections.synchronizedXXX`)的实现原理及使用方法,帮助开发者更好地理解和应用这些工具。 ... [详细]
  • 本文介绍如何在Spring Boot项目中集成Redis,并通过具体案例展示其配置和使用方法。包括添加依赖、配置连接信息、自定义序列化方式以及实现仓储接口。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • 本文探讨了如何在 F# Interactive (FSI) 中通过 AddPrinter 和 AddPrintTransformer 方法自定义类型(尤其是集合类型)的输出格式,提供了详细的指南和示例代码。 ... [详细]
  • 本文介绍了如何在 Node.js 中使用 `setDefaultEncoding` 方法为可写流设置默认编码,并提供了详细的语法说明和示例代码。 ... [详细]
  • Redux入门指南
    本文介绍Redux的基本概念和工作原理,帮助初学者理解如何使用Redux管理应用程序的状态。Redux是一个用于JavaScript应用的状态管理库,特别适用于React项目。 ... [详细]
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 本文目录一览:1、java方法执行顺序2、ja ... [详细]
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社区 版权所有