诸葛亮的锦囊妙计竟然是大名鼎鼎的Java设计模式:策略模式
应用场景
京东、天猫双十一,情人节商品大促销,各种商品有不同的促销活动
- 满减:满200减50
- 每满减:每满100减10
- 打折:买两件8折,三件7折
- 数量减:满三件减去最低价的一件
顾客在下单的时候可以选择其中几种来剁手,那么后端怎么来灵活的应对金额的计算呢,以后可能不同的节日还会有更多的促销活动,该怎么去计算订单的金额?
简单实现例子
public class OrderService {
public Order OrderPrices(Order order, String promotion) {
if (promotion.equals("promotion-1")) {
//计算金额
} else if (promotion.equals("promotion-2")) {
//计算金额
}
switch (promotion) {
case "promotion-1" :
//计算金额
break;
case "promotion-2" :
//计算金额
break;
}
return order;
}
}
上述的这种使用if else或者switch case方式并没有什么问题,但是促销活动会有很多种,这样的话,if else或者switch case里面的内容就会很多,那么怎么改进呢
也许会想到,每一种促销手段单独拿出来就会好一些,基于这个方法的设计原则:就是单一职责原则
public class OrderService {
public Order OrderPrices(Order order, String promotion) {
if (promotion.equals("promotion-1")) {
calPromotion1(order);
} else if (promotion.equals("promotion-2")) {
calPromotion2(order);
}
switch (promotion) {
case "promotion-1" :
calPromotion1(order);
break;
case "promotion-2" :
calPromotion2(order);
break;
}
return order;
}
public Order calPromotion1(Order order) {
return order;
}
public Order calPromotion2(Order order) {
return order;
}
}
上面的改进虽然好了一些,但是促销活动是不断变化的,一变化就需要修改OrderService类,而OrderService类是关于订单的,希望能够少改动,而不断变化的是促销算法
分析一下就可以知道,这里变化的是同一个行为的不同算法,那么再次改进
改进代码
同一行为的不同算法实现,我们可以用接口来定义行为,不同的算法分别去实现接口
设计原则:对修改关闭,对扩展开放
public interface PromotionAlgorithm {
Order promotionAlgorithm(Order order);
}
public class PromotionAlgorithm1 implements PromotionAlgorithm {
@Override
public Order promotionAlgorithm(Order order) {
System.out.println("满200减50");
return order;
}
}
public class PromotionAlgorithm2 implements PromotionAlgorithm {
@Override
public Order promotionAlgorithm(Order order) {
System.out.println("满2件打8折");
return order;
}
}
public class OrderService {
public Order OrderPrices(Order order, String promotion) {
if (promotion.equals("promotion-1")) {
return new PromotionAlgorithm1().promotionAlgorithm(order);
} else if (promotion.equals("promotion-2")) {
return new PromotionAlgorithm2().promotionAlgorithm(order);
}
switch (promotion) {
case "promotion-1" :
return new PromotionAlgorithm1().promotionAlgorithm(order);
case "promotion-2" :
return new PromotionAlgorithm2().promotionAlgorithm(order);
}
return order;
}
}
把每一种促销算法单独实现,然后使用,这就是策略模式的应用
类图:
策略模式
定义
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的用户而独立变化
意图
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替
主要解决问题
在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护
何时使用
一个系统有许多类,而区分它们的只是他们直接的行为
优缺点
优点:
1:各种算法可以随意切换
2:可以避免使用多重判断引起的麻烦
3:扩展性好
缺点:
1:策略类比较多
2:所有的策略类都需要对外暴露
下面看下类图:
涉及到的角色:
- 环境(Context)角色:持有一个Stratogy类的引用
- 抽象策略(Strategy)角色:这是一个抽象角色,通常有一个接口或抽象类实现,此角色给出了所有具体的策略类所需要的接口
- 具体策略(ConcreteStartegy)角色:包装了相关的算法或者行为
Context类:
public class Context {
private Strategy strategy;
/** 策略方法 */
public void contextInterface() {
strategy.strategyInterface();
}
}
Strategy类:
public interface Strategy {
/** 策略方法 */
void strategyInterface();
}
ConcreteStrategy类:
public class ConcreteStrategy implements Strategy{
/** 策略方法 */
@Override
public void strategyInterface() {
//do something
}
}
诸葛亮的锦囊妙计
当年赵云保护刘备入吴国迎娶美女,诸葛亮给了他三个锦囊,囊中有三个妙计,嘱咐赵云见机行事。这三个锦囊妙计是很符合策略模式的,看来诸葛亮不是策略模式的的始作俑者也是最初的实践者,下面是一个小例子:
锦囊妙计接口:
public interface SeminalVesicle {
/** 按计行事 */
String tricks();
}
按计行事实现类:
public class BackDoor implements SeminalVesicle {
/** 按计行事 */
@Override
public String tricks() {
return "走乔国老的后门";
}
}
public class GoBack implements SeminalVesicle {
/** 按计行事 */
@Override
public String tricks() {
return "骗刘备回去";
}
}
public class Retreat implements SeminalVesicle {
/** 按计行事 */
@Override
public String tricks() {
return "请孙夫人退兵";
}
}
赵云类:
public class ZhaoYun {
private SeminalVesicle seminalVesicle;
public ZhaoYun(SeminalVesicle seminalVesicle) {
this.seminalVesicle = seminalVesicle;
}
/** 按计行事 */
public String act() {
return seminalVesicle.tricks();
}
}
测试类:
public class Test {
public static void main(String[] args) {
ZhaoYun zhaoYun = new ZhaoYun(new Retreat());
System.out.println("赵云按计行事");
System.out.println(zhaoYun.act());
}
}
类图:
需要注意的是,如果策略比较多,差不多多于4个的时候,就需要考虑使用混合模式了,避免策略类膨胀
诸葛亮的锦囊妙计竟然是大名鼎鼎的Java设计模式:策略模式的更多相关文章
- java设计模式 策略模式Strategy
本章讲述java设计模式中,策略模式相关的知识点. 1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户.策略模式属于对象的 ...
- JAVA 设计模式 策略模式
用途 Title 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 策略模式是一种行为型模式. 结构
- 我的Java设计模式-策略模式
今天给大家说说田忌赛马的故事.如有雷同,纯属巧合!话说在战国时期,群雄割据,硝烟四起,茶余饭后还是少不了娱乐活动的,其中赛马是最火爆的.一天,孙膑看到田忌像个死鸡似的就知道肯定赛马又输给了齐威王,立马 ...
- Java设计模式—策略模式
1.策略模式(Strategy Pattern)是一种比较简单的模式,也叫做政策模式(PolicyPattern). 定义如下: Define a family of algorithms,e ...
- Java设计模式-策略模式详解
前言 在软件领域中,设计模式作为一种经典的开发实践常常需要我们去深入的理解,而策略模式作为设计模式的一种,使用频率也是相对来说比较高的,在Java中,当我们学习TreeSet集合的时候,就采用了经典的 ...
- Java 设计模式--策略模式,枚举+工厂方法实现
如果项目中的一个页面跳转功能存在10个以上的if else判断,想要做一下整改 一.什么是策略模式 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决 ...
- java设计模式--策略模式
策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 本文地址:http:// ...
- Java设计模式-策略模式(strategy)
策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户.需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无 ...
- Java设计模式——策略模式
策略模式的定义: 策略模式其实特别好理解,俗话说得好,条条大路通罗马,做的都是一件事,实现的方式却可以千万种,在这种情况下,如何使得每个人都可以根据自己的喜好来选择具体的方式,在调用时可以根据不同方式 ...
随机推荐
- idea没有错误提示的解决方法(一直处于错误分析中)
仅作记录,以防再次发生却不记得. 原文链接:https://blog.csdn.net/a755199443/article/details/90084316 问题描述:idea没有自动报错.例如随便 ...
- ElasticSearch 中的 Mapping
公号:码农充电站pro 主页:https://codeshellme.github.io 1,ES 中的 Mapping ES 中的 Mapping 相当于传统数据库中的表定义,它有以下作用: 定义索 ...
- 谈一下hashMap中put是如何实现的?
源码: Hash(key):计算出key的hash值. put方法详解: 1.如果table数组为null或者table数组的长度为0,则调用resize()方法扩容并返回table数组.数组的长度为 ...
- 如何吃透Python的面向对象(OOP)
本篇可乐和大家一起来吃透 Python 的面向对象,类和实例. 面向对象(OOP) 解释:面向对象它是一种编程的思想,将现实事物抽象化为编程对象. 举例说明:喝可乐 ① 选择自己根据配方买对应的材料 ...
- Java基本概念:类
一.描述 类是一种抽象的数据类型,它是对某一类事物整体的描述或定义,但是并不能代表某一个具体的事物. 例如,我们生活中所说的词语:动物.植物.手机.电脑等等.这些也都是抽象的概念,而不是指的某一个 具 ...
- Hive实现自增序列及常见的Hive元数据问题处理
Hive实现自增序列 在利用数据仓库进行数据处理时,通常有这样一个业务场景,为一个Hive表新增一列自增字段(比如事实表和维度表之间的"代理主键").虽然Hive不像RDBMS如m ...
- 《Asp.Net Core3 + Vue3入坑教程》-Net Core项目搭建与Swagger配置步骤
简介 <Asp.Net Core3 + Vue3入坑教程> 此教程仅适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 教程后 ...
- MySQL注入 利用系统读、写文件
目录 能读写文件的前提 Windows下的设置 Linux下的设置 没有读写权限的尝试 有SQL注入点,确认是否有读写权限 read load_file() load data infile() wr ...
- ss_port_change - 一键修改ss配置与Centos7的Firewall策略脚本
ss_port_change 修改ss配置与Centos7的Firewall策略脚本 注意是否需要修改config路径与ss服务的名 脚本的敏感字用了*代替 项目地址 Github 脚本 #!/bin ...
- 虚拟机测试cobbler,网络安装加载最后出现 dracut:/#
1.cobbler的几个重要概念: distro:发行版系统容,我理解为镜像来源,提供了kernel 和 initrd 文件以及repo源 profile:kickstart文件,用于定制系统,定制安 ...