前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Head first 设计模式之策略模式,来源于生活,用之于生活

Head first 设计模式之策略模式,来源于生活,用之于生活

作者头像
用户4361942
发布2019-05-24 17:01:59
4380
发布2019-05-24 17:01:59
举报
文章被收录于专栏:java程序员思维

为什么需要设计模式?

设计模式是软件设计中常见问题的通用可重用的解决方案,与语言无关。通过引入设计模式,可以更好的提高代码复用性、灵活性、扩展性。

程序设计原则

程序设计也需要遵循很多原则,开闭原则就是说对扩展开放,对修改关闭。里氏代换原则,任何基类可以出现的地方,子类一定可以出现。依赖倒转原则、接口隔离原则、迪米特法则、合成复用原则。

设计模式的分类

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户,属于行为型模式。

使用场景

电商网站支付方式,一般分为银联、微信、支付宝,可以采用策略模式,为每一种方式,作为一种支付方式的实现,如果哪一个支付方式方式,发生了变化,只要修改对应的实现即可,不需要修改调用的客户端,如果引入新的支付,如万里通支付,增加一个对应的万里通支付实现类,遵循了开闭原则。

dubbo,spring cloud Ribbon客户端负载均衡策略,都是采用的策略模式,dubbo有一致性hash均衡策略、最小活跃调用书均衡策略、随机均衡策略、轮询均衡策略。

RoundRobinRule 轮询 RandomRule 随机

AvailabilityFilteringRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数超过阈值的服务,然后对剩余的服务列表进行轮询

WeightedResponseTimeRule 权重根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。刚启动时,如果统计信息不足,则使用轮询策略,等信息足够,切换到 WeightedResponseTimeRule

RetryRule 重试 先按照轮询策略获取服务,如果获取失败则在指定时间内重试,获取可用服务

BestAvailableRule 选过滤掉多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

ZoneAvoidanceRule 符合判断server所在区域的性能和server的可用性选择服务

计算器的计算方式,加减乘除方法的实现也可以采用策略模式,如果加入一种新的计算取余,增加一种实现即可。

具体实现:

代码语言:javascript
复制
//糟糕的代码
public class BadCode {
 
 private double num1;
 private double num2;
 private String method;
 public BadCode(double num1, double num2, String method) {
 this.num1 = num1;
 this.num2 = num2;
 this.method = method;
 }
 
 public double calculate() {
 if("+".equals(this.method)){
 return num1 + num2;
 }else if("-".equals(this.method)){
 return num1 - num2;
 }else if("*".equals(this.method)){
 return num1 * num2;
 }else if("/".equals(this.method)){
 return num1/num2;
 }else{
 throw new RuntimeException("method error");
 }
 }
}

如果新加一种运算方法,需要修改calculate方法,增加一个else if 判断条件,代码的扩展性比较差,如果使用策略模式,可以改善这种情况,将容易修改的地方分离,便于扩展自由动态的选择。

定义计算接口

代码语言:javascript
复制
public interface Calculator {
 public double calculate(double num1,double num2);
}
代码语言:javascript
复制
//加法实现
public class OptionAdd implements Calculator{
 public double calculate(double num1, double num2) {
 return num1 + num2;
 }
}
//减法实现
public class OptionSubstract implements Calculator{
 public double calculate(double num1, double num2) {
 return num1 - num2;
 }
}
//乘法实现
public class OptionMultiply implements Calculator{
 public double calculate(double num1, double num2) {
 return num1 * num2;
 }
}
//除法实现
public class OptionDivide implements Calculator{
 public double calculate(double num1, double num2) {
 return num1 / num2;
 }
}
//定义计算
public class Context {
 private Calculator calculator;
 public Context(Calculator calculator) {
 this.calculator = calculator;
 }
 public double executeStrategy(int num1, int num2){
 return calculator.calculate(num1, num2);
 }
 public Calculator getCalculator() {
 return calculator;
 }
 public void setCalculator(Calculator calculator) {
 this.calculator = calculator;
 }
}
//测试类
public class Test {
 public static void main(String[] args) {
 Context context = new Context(new OptionAdd());
 double result = context.executeStrategy(1,3);
 System.out.println("add:" + result);
 context.setCalculator(new OptionSubstract());
 result = context.executeStrategy(1,3);
 System.out.println("substract:" + result);
 context.setCalculator(new OptionMultiply());
 result = context.executeStrategy(1,3);
 System.out.println("multiply:" + result);
 context.setCalculator(new OptionDivide());
 result = context.executeStrategy(1,3);
 System.out.println("divide:" + result);
 }
}

测试结果

上面只是简单的实现,实际应用开发过程中,需要和spring配合使用,将算法实现交给spring容器进行管理,客户端通过spring注入相应的bean,而不是像测试类一样,每次都创建一个实例。

策略模式的优缺点

优点:算法可以自由切换 避免使用多重条件判断 扩展性良好

缺点:策略类会增多 所有策略类都需要对外暴露

生活中的策略模式

去往某一个目的地,短距离可以选择步行、共享单车,中等距离可选择打车、地铁,长距离可选择高铁、飞机。不是一成不变的,可以自由切换。上班距离很短,平时可能步行,共享单车,如果哪一天起床晚了,赶时间,可以切换到打车模式。

我的启发

策略模式,就像一个可插拔的组件,就像电脑一样,如果硬盘坏了,我只要换一个硬盘而不是整个电脑,我可以选择不同的品牌,我也可以选择是机械的还是固态的,我可以使用不同的策略,因为所有的厂商,都遵循同一套标准,使用策略模式,能够拥有更好的灵活性。一架飞机,出现问题,通过系统检测,如果发动机有问题,把整个发动机进行替换,对于出现故障的发动机,再进行内部结构进行检测,使用同样的方法,进行检测和替换,直到找到真正的原因。设计模式来源于生活,使用于生活。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java程序员思维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档