应用场景

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

  • 满减:满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. tomcat部署项目问题

    tomcat部署项目的时候,报内存溢出,一种解决方案是直接添加内存,网上都有教程,如下: Windows下,在文件/bin/catalina.bat,Linux下,在文件/bin/catalina.s ...

  2. 谈一下HashMap的底层原理是什么?

    底层原理:Map + 无序 + 键唯一 + 哈希表 (数组+Entry)+ 存取值 1.HashMap是Map接口的实现类.实现HashMap对数据的操作,允许有一个null键,多个null值. Co ...

  3. 零信任三大技术之SDP

    SDP概述 SDP Software Defined Perimeter(软件定义边界),2013 年由云安全联盟 CSA提出. SDP 设计基本原则 1.信息隐身:隐藏服务器地址.端口,使之不被扫描 ...

  4. 微信小程序使用彩色图标(阿里巴巴 iconfont Symbol 的用法)微信小程序使用彩色图标(阿里巴巴 iconfont Symbol 的用法)

    前提 需要安装好 nodejs (略) 用于下载插件 安装插件 npm install mini-program-iconfont-cli --save-dev 初始化配置文件 npx iconfon ...

  5. XAPKInstaller - XAPK游戏包安装器

    XAPKInstaller 一个用于安装XAPK游戏包的安装器. 程序需要读写存储与获取已安装应用权限才可正常运行. 长按条目可显示文件的详细信息. SDK小于24(Android N)的设备会显示应 ...

  6. kubernetes Pod亲和性

    三种调度粘性,主要根据官方文档说明: NodeSelector(定向调度).NodeAffinity(Node亲和性).PodAffinity(Pod亲和性). 1.      nodeSelecto ...

  7. Codeforces 598D (ccpc-wannafly camp day1) Igor In the Museum

    http://codeforces.com/problemset/problem/598/D 分析:BFS,同一连通区域的周长一样,但查询过多会导致TLE,所以要将连通区域的答案储存,下次查询到该连通 ...

  8. day1_安装及建立数据库和表

    #第一份数据库及表create database library; use library; create table book( id int primary key, book_name char ...

  9. org.springframework.web.util.IntrospectorCleanupListener作用

    回收那些不会主动回收,导致内存泄漏的垃圾,如javabeans

  10. JSP、EL表达式、JSTL标签库干货(建议收藏)

    JSP(Java Server Pages)类似于ASP技术,它是在传统的网页HTML文件(.htm,.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件, ...