文章目录

  • 1.“组件协作”模式
  • 2.策略模式动机(Motivation)
  • 3.问题引入
  • 4.商场收银系统1.0
  • 5. 使用简单工厂模式
  • 6.简单工厂模式的缺陷
  • 7. 简单工厂模式和策略模式
  • 8.策略模式的优缺点
  • 9.策略与简单工厂结合

1.“组件协作”模式

“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合。 典型模式:
Strategy
Template Method
Observer/Event

2.策略模式动机(Motivation)

在运行时根据需要透明地更改对象的算法,将算法与对象本身解耦

3.问题引入

商场收银软件
输入单价和数量
算出每种商品的小计
记录商品的清单
记录总计

4.商场收银系统1.0

import java.util.Scanner;
public class Cash{public String list=" ";public Double totalPrice=0.00;   //声明一个double变量totalPrice来计算总计public void buttonOK(){Scanner scan=new Scanner(System.in);System.out.println("输入单价:");String price=scan.nextLine();scan=new Scanner(System.in);System.out.println("输入数量:");String num=scan.nextLine();Double xiaoji=Double.parseDouble(price)*Integer.parseInt(num);//声明一个xiaoji来计算每个商品的单价*数量后的合计list+="单价:"+price+",数量:"+num+",小计:"+xiaoji+"\n";//清单totalPrice+=xiaoji;//每个商品计入小计}public static void main(String[] args){Cash cash=new Cash();boolean flag=true;while(flag){           //循环终止条件可改cash.buttonOK();if(cash.totalPrice>10){flag=false;}}System.out.println("=============");System.out.println("清单:\n"+cash.list);System.out.println("总价:"+cash.totalPrice);
//如果商场商品打折
//加下拉选择框或输入折扣可以解决//即在buttonOK类中输入数量的下面加上
scan =new scanner(Systen.in);
System.out.println("输入折扣:");
String zhekou=scan.nextLine();
//并且小计的计算中需要改变如下:
Double xiaoji=Double.parseDouble(price)*Integer.parseInt(num)*Double.parseDouble(zhekou)/10;//如果增加满减促销活动或则折扣种类过多将会难以实现

5. 使用简单工厂模式

用简单工厂模式:
现金收费抽象类CashSuper,里有收取现金的方法acceptCash()
有三种方案:正常收费,打折收费,满减收费
工厂类,封装现金收费类

import java.util.Scanner;
//现金收取父类
abstract class CashSuper{public abstract double acceptCash(double money);
}
//正常收费类
class CashNormal extends CashSuper{@Overridepublic double acceptCash(double money){return money;}
}
//打折收费类,继承CashSuper
class CashRebate extends CashSuper{private double discount=0.00;//初始化时,必须输入折扣率,如八折就是0.8public CashRebate(double discount){this.discount=discount/10;}@overridepublic double acceptCash(double money){return this.discount*monwy;//返利收费,继承CashSuper
class CashReturn extends CashSuper{private double baseCash;//基础金额private double returnCash;//返现金额//初始化时必须要输入返利条件和返回值,比如满300反100,则baseCash为300,returnCash为100public CashReturn(double baseCash,double reurnCash){this.baseCash=baseCash;this.returnCash=returnCash;}@overrridepublic double acceptCash(double money){double result=money;if(money>=baseCash)//若大于返利条件,则需要减去返利值result=money-Math.floor(money/baseCash)*returnCash;//函数Math.floor(x)返回小于x的最大整数值return result;  }public double getBaseCash(){   return baseCash;   }public void setBaseCash(double baseCash)  {   this.baseCash=baseCash;   }public double getReturnCash() {  return returnCash;   }public void setReturnCash(double returnCash) {  this.returnCash=returnCash;  }
}//现金收取工厂
class CashAcceptFactory{//根据条件生成相应的对象//静态方法特点可以使用类名调用public static CashSuper createCashAccept(String type,double discount,double basePrice,double returnPrice){CashSuper cs=null;if("1".equals(type)) cs=new CashNormal();else if("2".equals(type)) cs=new CashRebate(discount);elseif("3".equals(type)) cs=new CashReturn(basePrice,returnPrice);}
}//客户端程序
public class program{public static void main(String[] args){boolean flag=true;String list="";Double totalPrice=0.00;while(flag){scanner scan=new Scanner(System.in);System.out.println("输入单价:");String price=scan.nextLine();scan=new Scanner(System.in);System.out.println("输入数量:");String num=scan.nextLine();scan=new Scanner(System.in);System.out.println("输入折扣类型(1无折扣 2打折 3满减):");String type=scan.nextLine();double discount=0.0d;double basePrice=0;double returnPrice=0;if("2".equals(type)){Scan=new Scanner(System.in);System.out.println("输入折扣:");discount=Double.parseDouble(scan.nextLine());}if("3".equals(type)){scan=new Scanner(System.in);System.out.println("返回基础金额:");basePrice=Double.parseDouble(scan.nextLine());scan=new Scanner(System.in);System.out.println("返现金额:");returnPrice=Double.parseDouble(scan.nextLine());}Double xiaoji=Double.parseDouble(pric。e)*Integer.parseInt(num);CashSuper cs=CashAcceptFactory.createCashAccept(type,discount,basePrice,returnPrice);   //类名调用静态方法double xiaoji=cs.accpetCash(xianjin);list+="单价:"+price+",数量:"+num+",折扣:"+discount+",小计:"+xiaoji+"\n";totalPrice+=xiaoji;if(totalPrice>10){flag=false;}}System.out.println(list);System.out.println("总价:"+totalPrice);}
}

6.简单工厂模式的缺陷

简单工厂模式只是解决对象的创建问题,虽然工厂可能已经包括了所有的收费方式,但商场可能经常地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂,以致代码需要重新编译部署
不符合开闭原则,所以不是最好地办法。

原因是因为现金收取工厂与具体收费类是紧耦合的,需要改进成现金收取工厂中不要出现具体收费类,
而且现金工厂实际是现金收取控制类,可以用收费类的父类来代替具体收费类,并为其传入具体收费方式对象。
代码如下


//现金收取控制类
class CashContext{private CashSuper cs; //声明一个现金收费父类对象public CashContext(CashSuper csuper){//通过构造方法,传入具体的收费策略对象(正常
打折或返利)this.cs=csuper;  }public double GetResult(double money){//根据不同收费策略获得合计结果return cs.acceptCash(money);    }
}//改造后的客户端代码
public class program{public static void main(String[] args){boolean flag=true;String list="";Double totalPrice=0.00;while(flag){Scanner scan=new Scanner(System.in);System.out.println("输入单价:");String price=scan.nextLine();scan=new Scanner(System.in);System.out.println("输入数量:");String num=scan.nextLine();scan=new Scanner(System.in);System.out.println("输入折扣类型(1无折扣2打折3满减):");String type=scan.nextLine();double discount=0.0d;double basePrice=0;double returnPrice=0;CashSuper cs=null;       //改造加入的if("1".equals(type))cs=new CashNormal();else if("2".equals(type)){scan=new Scanner(System.in);System.out.println("输入折扣:");discount=Double.parseDouble(scan.nextLine());cs=new CashRebate(discount);}else if("3".equals(type)){scan=new Scanner(System.in);System.out.println("返现基础金额:");basePrice=Double.parseDouble(scan.nextLine());scan=new Scanner(System.in);System.out.println("返现金额:");returnPrice=Double.parseDouble(scan.nextLine());cs=new CashReturn(basePrice,returnPrice);}Double xianjin=Double.parseDouble(price)*Integer.parse(num);CashContext cc=new CashContext(cs);//将相应的策略对象作为参数传入CashContext构造函数中double xiaoji=cc.GetResult(xianjin);list+="单价:"+price+",数量:"+num+",折扣:"+discount+",小计:"+xiaoji+"\n";totalPrice+=xiaoji;if(totalPrice>10){flag=false;}}System.out.println(list);System.out.println("总价:"+totalPrice);}
}

策略模式下加入新的方法
只需要增加新的方法类
以及修改客户端即可

7. 简单工厂模式和策略模式

简单工厂模式:传条件进工厂类,工厂类就会返回一个对象给调用者,供调用者使用——最终给用户使用的是工厂返回的类
策略模式:创建一个Context类,(可以看作是工厂模式中工厂类的替代品)的对象context,传一个要使用的策略实例对象A个context,然后使用context调用A中的某些方法——最终给用户的是Context类。

8.策略模式的优缺点

策略类之间可以自由切换(由于策略类都实现一个接口)
避免使用多重条件选择语句,充分体现面向对象设计思想
扩展性良好,增加一个新的策略只需要添加一个具体的策略类,不需要改变原有的代码,符合“开闭原则”
缺点:
把分支判断又放回到客户端,需要改变需求算法时,还是要改变客户端程序
缺乏工厂模式的优势,客户端必须知道所有策略类,并自行决定使用哪一个策略类。
策略类增多

9.策略与简单工厂结合

针对策略模式的缺点:分支判断在客户端,改变算法时,要更改客户端的程序,意味着暴露了所有具体策略类
解决:其他不变,改变CashContext类,把分支判断放到环境角色(CashContext 类)中

class CashContext{private CashSuper cs=null;//声明一个现金收费父类对象public CashContext()//注意构造函数的参数不再是一个具体策略对象{Scanner scan=new Scanner(System.in);System.out.println("输入折扣类型(1无折扣2打折3满减):");String type=scan.nextLine();double discount=0.0d;double basePrice=0;double returnPrice=0;if("1".equals(type))  cs=new CashNormal();    //此处不同else{  //将实例化具体策略的过程移到Context类中,简单工厂的应用if("2".equals(type)){scan=new Scanner(System.in);System.out.println("输入折扣:");discount=Double.parseDouble(scan.nextLine());cs=new CashRebate(discount);     //此处不同}elseif("3".equals(type)){scan=new Scanner(System.in);System.out.println("返现基础金额:");basePrice=Double.parseDouble(scan.nextLine());scan=new Scanner(System.in);System.out.println("返现金额:");returnPrice=Double.parseDouble(scan.nextLine());cs=new CashReturn(basePrice,returnPrice);  //**此处不同**}}public double GetResult(double money){  return cs.acceptCash(money);  }
}//客户端
public class program{public static void main(String[] args){boolean flag=true;String list="";Double totalPrice=0.00;while(flag){Scanner scan=new Scanner(System.in);System.out.println("输入单价:");String price=scan.nextLine();scan=new Scanner(System.in);System.out.println("输入数量:");String price=scan.nextLine();Double xianjin=Double.parseDouble(price)*Integer.parseInt(num);CashContext cc=new CashContext();     //**此处不同**double xiaoji=cc.GetResult(xianjin);     //list+="单价:"+price+",数量:"+num+",小计:"+xiaoji+"\n";totalPrice+=xiaoji;if(totalPrice>10){  flag=false;   }  //标志可根据需要更改System.out.println(list);System.out.println("总价:"+totalPrice);}
}

“组件协作”模式----策略模式(Strategy Pattern)相关推荐

  1. 进阶学习之旅-设计模式之(委派模式策略模式)

    文章目录 1.课程学习目标 2.内容定位 3.委派模式详解 3.1委派模式的定义 3.2 demo案例 3.2.1模拟Boss指派任务给Leader 由员工完成任务执行 3.2.2 模拟spring ...

  2. 3.js模式-策略模式

    1. 策略模式 策略模式定义一系列的算法,把它们封装起来,并且可以互相替换. var strategies = { isNonEmpty: function(value,errMsg){ if(val ...

  3. 23种模式——策略模式

    目录 策略模式 策略模式的收银软件 策略模式的特点 使用场景 优缺点 策略模式和工厂模式的结合 策略(Strategy)模式 本质:分离算法,选择实现. 策略模式:针对一组算法,将每一个算法封装到具有 ...

  4. java-抽象工厂模式+工厂方法模式+策略模式简单应用实战(登录场景)

    前言 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经过分类的.代码设计经验的总结. 使用设计模式的目的:为了代码可重用性.让代码更容易被他人理解.保证代码可靠性. 设计模式 ...

  5. 混合模式(工厂方法模式+策略模式+门面模式)

    混合模式(工厂方法模式+策略模式+门面模式) 使用这三种模式设计一个简单的计算器程序:计算器是用于计算数值之间进行数学计算后所获得的值.它包含基本的"加减"功能.以上对以上需求进行 ...

  6. 行为模式---策略模式和状态模式

    策略模式 状态模式 策略模式和状态模式对比 策略模式 策略模式类图: 策略模式重在抽象行为,即将行为抽象为具体的类,调用的时候动态选择行为,策略模式不同策略之间可以相互替换,并不影响最终结果,比如定义 ...

  7. 设计模式 — 行为型模式 — 策略模式

    目录 文章目录 目录 策略模式 应用场景 代码示例 策略模式 策略模式中,首先定义了一系列不同的算法,并把它们一一封装起来,然后在策略类中,使这些算法可以相互替换.这意味着,让一个类的行为(算法)可以 ...

  8. 模板模式+策略模式优化

    前言 写在最前面,最近在项目中发现一部分代码,可以用模板模式+策略模式来进行优化. 背景 业务中,系统中对订单状态的处理,需要发送对用户短信发送或者微信推送等操作. 发送短信和微信推送钱,需要处理逻辑 ...

  9. 工厂模式+策略模式组合实现电商促销活动

    项目中大多数设计模式都是组合使用的,对于单个设计模式小伙伴们可以去菜鸟教程学习一下,下面使用 Java 实现的工厂模式+策略模式组合实现电商促销 首先,根据策略的不同,一些需要优惠计算,一些需要普通计 ...

  10. 工厂模式+策略模式+反射机制解决系统功能模块相似的问题

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 背景 痛点 一.如何根据不同条件获取不同的数据库Mapper? 二.如何根据不同条件创建相应的数据库实体对象? 总结 背景 ...

最新文章

  1. VSCode 搭建Vue开发环境之Vue CLI
  2. 控制器描述者(ControllerDescriptor),行为方法描述者(ActionDescriptor),参数描述者(ParameterDescriptor)的小结...
  3. AGG第三十五课 gsv_text 渲染ASCII字符
  4. 工信部王卫明:我国5G研发开局良好
  5. 数据中心机房消防演练方案
  6. java logger 静态,java11教程--公共静态接口System.Logger
  7. python数据结构和算法3 栈、队列和排序
  8. 加密货币的时代,真的来临了吗?
  9. (3)Node.js APIS
  10. SAP License:CO生产订单
  11. seaweedfs java_seaweedfs-java-client
  12. 软件测试:什么是图灵测试
  13. poco linux,centos7.2 安装poco
  14. 关于开源软件开发的若干问题
  15. Windows7 开机自启脚本
  16. SQLMAP插件tamper编写与使用
  17. Pytorch-Lightning--Tuner
  18. 程序人生——Hello P2P
  19. 利用samba漏洞入侵linux主机(samba低版本漏洞利用)
  20. UEFI启动阶段学习SEC阶段和PEI阶段_2020-05-12

热门文章

  1. matlab绘制频率响应特性曲线,MATLAB环境下频率响应曲线的绘制方法
  2. 【java 高并发编程之JUC】高阶JUC特性总结
  3. Ununtu 18.04 安装Carla 0.9.13 以及Carla ros bridge 超级避坑指南(更新于2022.10.20)
  4. 自己动手做AI:Google AIY开发工具包解析
  5. 小学计算机在线操作平台,中小学在线学习有哪些平台
  6. 给你一个数组 nums ,数组中有 2n 个元素,按 [x1,x2,...,xn,y1,y2,...,yn] 的格式排列。 请你将数组按 [x1,y1,x2,y2,...,xn,yn] 格式重新排
  7. 分享两个免费在线shell
  8. 利用Creo3.0提供的ProToolkit工具包,结合VS2012进行二次开发时开发环境的配置
  9. php网站建设实训引言_PHP的开发环境搭建与网站设计实现分析论文
  10. css3雨滴掉落水面网页动画