应用场景

京东、天猫双十一,情人节商品大促销,各种商品有不同的促销活动

  • 满减:满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:所有的策略类都需要对外暴露

下面看下类图:



涉及到的角色:

  1. 环境(Context)角色:持有一个Stratogy类的引用
  2. 抽象策略(Strategy)角色:这是一个抽象角色,通常有一个接口或抽象类实现,此角色给出了所有具体的策略类所需要的接口
  3. 具体策略(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设计模式:策略模式的更多相关文章

  1. java设计模式 策略模式Strategy

    本章讲述java设计模式中,策略模式相关的知识点. 1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户.策略模式属于对象的 ...

  2. JAVA 设计模式 策略模式

    用途 Title 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 策略模式是一种行为型模式. 结构

  3. 我的Java设计模式-策略模式

    今天给大家说说田忌赛马的故事.如有雷同,纯属巧合!话说在战国时期,群雄割据,硝烟四起,茶余饭后还是少不了娱乐活动的,其中赛马是最火爆的.一天,孙膑看到田忌像个死鸡似的就知道肯定赛马又输给了齐威王,立马 ...

  4. Java设计模式—策略模式

    1.策略模式(Strategy Pattern)是一种比较简单的模式,也叫做政策模式(PolicyPattern). 定义如下:     Define a family of algorithms,e ...

  5. Java设计模式-策略模式详解

    前言 在软件领域中,设计模式作为一种经典的开发实践常常需要我们去深入的理解,而策略模式作为设计模式的一种,使用频率也是相对来说比较高的,在Java中,当我们学习TreeSet集合的时候,就采用了经典的 ...

  6. Java 设计模式--策略模式,枚举+工厂方法实现

    如果项目中的一个页面跳转功能存在10个以上的if else判断,想要做一下整改 一.什么是策略模式 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决 ...

  7. java设计模式--策略模式

    策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 本文地址:http:// ...

  8. Java设计模式-策略模式(strategy)

    策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户.需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无 ...

  9. Java设计模式——策略模式

    策略模式的定义: 策略模式其实特别好理解,俗话说得好,条条大路通罗马,做的都是一件事,实现的方式却可以千万种,在这种情况下,如何使得每个人都可以根据自己的喜好来选择具体的方式,在调用时可以根据不同方式 ...

随机推荐

  1. C++单链表反转、两有序链表合并仍有序

    1 #include<iostream> 2 3 struct Node 4 { 5 int data; 6 Node *next; 7 }; 8 9 typedef struct Nod ...

  2. 如何将文件夹取消svn关联

    随便在什么目录新建一个文本文件,文件名随便,将文本文件打开,将下面的文字复制到文本文件中: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHI ...

  3. 在 c++ 程序中出现CtrIsValidHeapPointer问题

    在c++程序中出现CtrIsValidHeapPointer问题, 我发现的原因是申请了大量动态数组但是并没有把他们初始化 为数组赋初始值便可以很好解决这一问题.

  4. Latency 和 Delay 区别

    时延:Latency 指的是一个报文进入一台设备以致这台设备所经历的时间.实际上考验的是报文在这台设备上消耗的时间.时间越短,这台设备的性能越高.   延时:Delay 是指一个操作和另个一个操作之间 ...

  5. AOP面试造火箭始末

    本文已整理致我的github地址,欢迎大家 star 支持一下 这是一个困扰我司由来已久的难题,Dubbo 了解过吧,对外提供的服务可能有多个方法,一般我们为了不给调用方埋坑,会在每个方法里把所有异常 ...

  6. CCF(URL映射:80分):字符串处理+模拟

    URL映射 CCF201803-3 #include<iostream> #include<cstdio> #include<cstring> #include&l ...

  7. [个人总结]pip安装tensorboard太慢

    在执行pip install语句的时候直接指定国内豆瓣的镜像源进行下载: pip install -i https://pypi.douban.com/simple 你想下载的包的名称 例如下载ten ...

  8. JVM笔记 -- JVM的发展以及基于栈的指令集架构

    2011年,JDK7发布,1.7u4中,开始启用新的垃圾回收器G1(但是不是默认). 2017年,发布JDK9,G1成为默认GC,代替CMS.(一般公司使用jdk8的时候,会通过参数,指定GC为G1) ...

  9. 导出文件,responseType设置了blob,实际返回了JSON格式的错误信息的处理方式

    需求:导出文件 问题描述:由于后台直接返回的文件流,在请求下载的方法中将XHR 的 responseType 指定为 blob 或者 arraybuffer.但并不是每次的操作都是成功的,所以在接口错 ...

  10. 【linux】Linux删除文件后磁盘依旧占用空间的问题

    转自https://blog.51cto.com/2483526/798379 感谢 1.用df 检查发现/根目录可用空间为0 [root@/]#df -h 2.用du检查发现各目录占用的空间都很少, ...