设计模式之策略模式:让你的代码灵活应对不同的算法 | 京东云技术团队
作为一个程序员,我们经常会面临着在不同的情况下选择不同的算法来解决问题的需求。这种情况下,策略模式是一个非常有用的设计模式。在本文中,我将向你介绍策略模式的概念、结构以及如何应用这个模式来使你的代码更灵活。
1.什么是策略模式?
策略模式是一种行为型设计模式,它允许在运行时根据不同的情况选择算法的行为。这意味着我们可以将不同的算法封装成不同的策略类,并通过一个统一的接口来调用这些策略。
2.策略模式的结构
策略模式包括以下几个角色:
上下文(Context):持有一个策略对象的引用,并在需要时调用策略对象的方法。上下文可以根据具体情况选择不同的策略。
策略(Strategy):定义了一个公共接口,用于封装不同的算法。这个接口通常只有一个方法,即执行算法的方法。
具体策略(ConcreteStrategy):实现了策略接口,提供具体的算法实现。每个具体策略类都代表了一种特定的算法。
策略模式的关键在于上下文持有一个策略对象的引用,并且通过调用策略对象的方法来执行具体的算法。这种方式使得上下文变得非常灵活,可以根据不同的需求在运行时切换算法。
3.策略模式的应用场景
策略模式适用于以下情况:
- 当需要在运行时动态地选择算法实现时,可以使用策略模式。
- 当一个类有多个行为变种,并且这些行为可以灵活地切换时,策略模式可以提供一种优雅的解决方案。
例子(1)例如,在一个电商网站中,我们可能需要根据不同的支付方式来支付购物车的商品。可以是信用卡,当然也可以是京东支付、支付宝支付等等,这时,我们可以将每种支付行为封装成一个具体策略类,然后通过上下文选择合适的支付方式进行支付。
也许你可能见过类似的代码
if(payType==CreditCardType){ System.out.println("使用信用卡支付:" + amount + " 元"); // 实现具体的信用卡支付逻辑 }else if(payType==jdPayType){ System.out.println("使用京东支付:" + amount + " 元"); // 实现具体的京东支付逻辑 }else if(payType==alipayType){ System.out.println("使用支付宝支付:" + amount + " 元"); // 实现具体的支付宝支付逻辑 }else{ System.out.println("没实现,白嫖叭"); }
好了,这时候微信一看,为啥没把微信支付加上,赶紧支持。研发小哥哥加班修改逻辑如下:
if(payType==creditCardType){ System.out.println("使用信用卡支付:" + amount + " 元"); // 实现具体的信用卡支付逻辑 }else if(payType==jdPayType){ System.out.println("使用京东支付:" + amount + " 元"); // 实现具体的京东支付逻辑 }else if(payType==alipayType){ System.out.println("使用支付宝支付:" + amount + " 元"); // 实现具体的支付宝支付逻辑 }else if(payType==wxPayType){ System.out.println("使用微信支付:" + amount + " 元"); // 实现具体的微信支付逻辑 }else{ System.out.println("没实现,白嫖叭"); }
代码修改后,看着挺清晰明了,但是有一个问题,如果之后还有其他如抖音支付、乱七八糟支付的话我们就要一直修改这个类,一直添加 ...else if...
很明显违背了面向对象设计的六大原则之二:单一职责、开闭原则(对扩展开放、对修改关闭),六个违背俩,这活没法干了!
下面演示了如何使用策略模式来实现不同的支付方式:
// 定义一个支付的策略接口 public interface PaymentStrategy { //这只是个测试场景,真实场景下应该没人用double类型叭 void pay(double amount); } // 具体策略实现 // 信用卡支付 public class CreditCardPaymentStrategy implements PaymentStrategy { public void pay(double amount) { System.out.println("使用信用卡支付:" + amount + " 元"); // 实现具体的信用卡支付逻辑 } } // 京东支付 public class JdPaymentStrategy implements PaymentStrategy { public void pay(double amount) { System.out.println("使用京东支付:" + amount + " 元"); // 实现具体的京东支付逻辑 } } //省略... // 支付宝支付 // 微信支付 // 上下文 public class ShoppingCart { private PaymentStrategy paymentStrategy; public void setPaymentStrategy(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; } public void checkout(double amount) { // 调用策略对象的支付方法 paymentStrategy.pay(amount); } } // 使用示例 public class Main { public static void main(String[] args) { ShoppingCart cart = new ShoppingCart(); // 设置使用信用卡支付策略 cart.setPaymentStrategy(new CreditCardPaymentStrategy()); cart.checkout(1000.00); // 设置使用jd支付策略 cart.setPaymentStrategy(new JdPaymentStrategy()); cart.checkout(2000.00); //如果还想用其他支付 就继续写啊 } }
在上面的例子中,PaymentStrategy是策略接口,CreditCardPaymentStrategy和PayPalPaymentStrategy是具体的策略实现。ShoppingCart是上下文,通过setPaymentStrategy方法来设置不同的支付策略,并通过checkout方法调用具体策略的支付方法。看看,是不是可以通过扩展来增加支付方式。每个子类只实现具体的某种支付的策略。
例子(2)实现一个简单的计算器(整数),简单想一想也许涉及以下几种计算方式:加减乘除,也许有人会这样实现,但是我想一定不是你,聪明的你应该已经学会了策略模式在这种场景下的应用
试想 如果我想增加取余操作呢?
int num1 = 10; int num2 = 5; String operator = "+"; if (operator.equals("+")) { int result = num1 + num2; System.out.println("加法结果:" + result); } else if (operator.equals("-")) { int result = num1 - num2; System.out.println("减法结果:" + result); } else if (operator.equals("*")) { int result = num1 * num2; System.out.println("乘法结果:" + result); } else if (operator.equals("/")) { if (num2 != 0) { int result = num1 / num2; System.out.println("除法结果:" + result); } else { System.out.println("除数不能为零"); } } else { System.out.println("无效的运算符"); }
4.总结
策略模式是一种灵活、可扩展的设计模式,它通过将算法封装成策略类来实现不同的行为变种。使用策略模式可以提高代码的可维护性和复用性,同时也符合面向对象设计的原则。
希望本文的介绍对你理解策略模式有所帮助,也希望你能在实际项目中运用到这个强大的设计模式!
作者:京东零售 闫先东
来源:京东云开发者社区 转载请注明来源

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
记一次MySQL5初始化被kill的问题排查 | 京东云技术团队
写在前面 由于测试环境JED申请比较繁琐,所以Eone提供了单机版Mysql供用户使用,近期Eone搭建Mysql5的时候发现莫名被kill了,容器规格是4C8G,磁盘30G 这不科学,之前都是可以的,镜像没变,配置没变,咋就不行了呢,一定不是我的问题,是机器的问题 问题排查 重现 通过多次搭建mysql5进行采样,发现并不是稳定复现,有一些容器是可以正常启动提供服务的,找到被mysql服务被kill的容器日志,发现是MySQL初始化被kill了, /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --datadir=/export/data/mysql/data --user=admin --initialize-insecure mysql配置文件: [client] socket=/tmp/mysql.sock [mysqld] basedir=/usr/local/mysql datadir=/export/data/mysql/data port=...
- 下一篇
Opencv入门篇:简介与基本使用 | 京东物流技术团队
1 Opencv简介 Opencv是计算机视觉中经典的专用库,其支持多语言,跨平台,功能强大。Opencv-Python为Opencv提供了Python接口,使得使用者在Python中能够调用C/C++,在保证易读性和运行效率的前提下,实现所需的功能。 Opencv是由Gray Bradsky于1999年在英特尔创立,第一版于2000年问世。Vadim Pisarevsky加入Gary Bradsky,一起管理因特尔的俄罗斯软件Opencv团队。 2005年,Opencv用于Stanley,该车赢得了2005年DARPA挑战赛的冠军。后来,在Willow Garage的支持下,它的积极发展得以继续,由Gary Bradsky和Vadim Pisarevsky领导了该项目。Opencv现在支持与计算机视觉和机器学习有关的多种算法,并且正在日益扩展。 Opencv支持多种编程语言,例如C++, Python, Java等,并且可以再Windows , Linux , OS X , Android和IOS等不同平台上使用。基于CUDA和OpenCL的高速GPU操作的接口也在积极开发中。 Op...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库