JAVA设计模式之策略模式 - Strategy
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
介绍
什么是策略模式(Strategy Pattern)
在软件开发过程中常常遇到这样的情况, 实现某一个功能有很多种算法或实现策略, 我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能. 如果将这些算法或者策略抽象出来, 提供一个统一的接口, 不同的算法或者策略有不同的实现类, 这样在程序客户端就可以通过注入不同的实现对象来实现算法或者策略的动态替换, 这种模式的可扩展性和可维护性也更高, 这就是策略模式.
策略模式的定义(Strategy Pattern)
策略模式: 定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立与使用算法的客户.(摘抄于Head First设计模式)
简单理解: 定义了一系列算法,每个算法封装起来,各个算法之间可以互相替换,且算法的变化不会影响到使用算法的客户,属于行为型模式.
使用场景
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
- 需要安全的封装多种同一类型的操作时;
- 出现同一抽象类有多个字类, 而有需要使用 if-else 或者 switch-case 来选择具体字类时;
例如:
或出现大量 if-else 判断时可以使用策略模式优化代码.
例如电商网站支付方式,一般分为银联,微信,支付宝,可以采用策略模式,每一种方式作为一种支付方式的实现,如果哪一个支付方式发生变化,只需要修改对应的实现即可,不需要修改调用的客户端,如果引入新的支付方式,如:随行付,则只需要增加一个对应的随行付实现类即可,遵循开闭原则.
组成部分(三个角色)
1. 抽象策略(Strategy):
通常由接口或抽象类实现. 定义了多个具体策略的公共接口, 具体策略中各种不同的算法以不同的方式实现这个接口; Context使用这些接口调用不同实现的算法.
2. 具体策略(ConcreteStrategy):
实现了Strategy接口或继承与抽象类, 封装了具体的算法和行为.
3. 环境类(Context):
持有一个公共策略接口的引用(Strategy), 直接给客户端调用.
优缺点及重点
优点:
- 每个算法单独封装, 减少算法与算法调用者之间的耦合;
- 算法可以自由切换;
- 避免使用多重条件判断;
- 扩展性良好;
缺点:
- 策略类会增多.
- 所有策略类都需要对外暴露.
重点
- 给对象传入什么样的策略, 就执行什么样的动作.
实现
类图
说明: 代码来自Head First设计模式中SimUDuck的示例.
代码结构:
抽象策略(Strategy):
/**
* 飞行行为
*/
public interface FlyBehavior {
//各种飞行实现
public void fly();
}
具体策略(ConcreteStrategy):
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying!");
}
}
环境类(Context):
/**
* 鸭子类
*/
public abstract class Duck {
//持有一个公共策略接口的引用
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public void swim() {
System.out.println("我会游泳...");
}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
//提供set方法, 使鸭子可以动态改变飞行策略
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
//提供set方法, 使鸭子可以动态改变叫声策略
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
/**
* 绿头鸭
*/
public class MallardDuck extends Duck {
@Override
public void display() {
System.out.println("绿头鸭");
}
public MallardDuck() {
/*MallardDuck 继承 Duck, 所以具有quackBehavior 和 flyBehavior实例变量
当MallardDuck实例化时, 它的构造器会把继承的quackBehavior,
flyBehavior实例变量初始化成Quack,FlyWithWings类型的新实例
*/
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
}
测试类:
public static void main(String[] args) {
Duck mallard = new MallardDuck();
//飞行
mallard.performFly();
//改变鸭子行为(传入飞行策略)
mallard.setFlyBehavior(new FlyRocketPowered());
mallard.performFly();
//叫声
mallard.performQuack();
}
执行结果:
I'm flying!
I'm flying with a rocket!
呱呱叫
生活中的策略模式(我的猜想)
俗话说: 人是铁饭是钢, 一顿不吃饿的慌;吃饭也有策略模式, 你晓得嘛.
人(环境类)饿了要吃饭(抽象策略), 但是吃什么你知道吗? 这时你的大脑就会调集你的毕生功力(经验, 生活经历, 常识等等),来知道有哪些东西是可以吃的,比如鸡腿,面包或粥等等(具体策略,暴露所有策略).大脑选择(动态选择策略)吃其中的一种或多种食物来应对身体的不满.
生活中这样的例子还有很多,网上购物(不同的商品即: 具体策略), 世界那么大, 我想去转转.(转转的方式即: 具体策略)等.
结语
设计模式源于生活
JAVA设计模式之策略模式 - Strategy的更多相关文章
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- Java设计模式之策略模式(Strategy)
前言: 最近一直在学习基于okHttp网络请求,学习的过程中就想起了之前项目中有这么一个需求不同的接口要采用不同的加密方式,比如登录之前要采用RSA加密,登录之后要采用AES加密,当时是采用靠传递一个 ...
- 反馈法学习设计模式(一)——策略模式Strategy Pattern
简介(Introduction) 之前学习Java8实战时,遇到一个很好的策略模式示例.便想着借着这个示例结合反馈式的方法来,学习策略设计模式,也以便后面反复琢磨学习. 首先我们通过练习,逐步写出符合 ...
- 8.6 GOF设计模式四: 策略模式… Strategy Pattern
策略模式… Strategy Pattern 在POS系统中,有时需要实行价格优惠, 该如何处理? 对普通客户或新客户报全价 对老客户统一折扣5% 对大客户统一折扣10% 注:课件 ...
- 二十四种设计模式:策略模式(Strategy Pattern)
策略模式(Strategy Pattern) 介绍定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例有一个Message实体类,对它的操作有 ...
- Java设计模式1——策略模式(Strategy Pattern)
最近觅得一本好书<您的设计模式>,读完两章后就能断言,一定是一头极品屌丝写的,而且是专写给开发屌丝男的智慧枕边书,小女子就委屈一下,勉强看看,人笨,谁让他写得这么通俗易懂呢!为了加深理解, ...
- JAVA设计模式一策略模式(Strategy Pattern)
什么是设计模式? 就是一些经验.让程序代码更具弹性.好维护.代码复用的经验.而且设计模式都遵从一些OO设计原则. 题外话:以下罗列出常用的OO设计原则:链接 本文章介绍策略模式(Strategy Pa ...
- Java设计模式之策略模式(Strategy Pattern)
简介 策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 组成 1.抽象策略角色(Strategy): 策略类,通常由一个接口或者抽象类实现. 2.具 ...
- 折腾Java设计模式之策略模式
博客原文地址 简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. ...
随机推荐
- 最新版ADT(Build: v22.6.2)总是引用appcompat_v7的问题
昨天在ADT Manager里更新了一些组件,结果ADT不支持.索性直接下载了最新的ADT.但是发现无论创建什么类型的应用(无论支持的最低API是多少,或者是不是用模板),都会在创建应用的同时创建一个 ...
- CodeForces - 597C:Subsequences (主席树+DP)
For the given sequence with n different elements find the number of increasing subsequences with k + ...
- 基于Jenkins+Gitlab的自动化部署实战
故事背景 一个中小型企业,是典型的互联网公司,当初期的时候可能运维只能标配到2~3人,此时随着公司的发展,项目会逐渐增多.前期部署项目可能都是手动的, 俗称“人肉部署”,这简直是无比的痛苦,不能忍受的 ...
- python装饰器执行顺序
. python 装饰器 1) 2层装饰器 def decorator(func): # TODO def wrapper(*args, **kwargs): # TODO func(*args, * ...
- bzoj 4398 福慧双修——二进制分组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 如果枚举1号点走哪些点出去,就从那些点出发跑多源最短路即可.最短路不会重复经过一条边. ...
- AndroidStudio删除项目
右键左上角的 项目名 右键 > delete 磁盘里的文件还需要手动删除
- JavaScript-Tool:validate.js-un
ylbtech-JavaScript-Tool:validate.js 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 0. http://validatejs. ...
- APP开发过程中需求变更流程
在APP开发过程中,不可避免的会有需求变更,从以往项目开发过程总结发现,需求变更太频繁,产品一句话需求,没有形成良好的版本迭代概念,频繁的变动影响开发交付日期,但是交付日期又是定死的,严重拖累了开发及 ...
- 2.7 HBase架构深入剖析
一. 1.client 整个HBase集群的访问入口: 使用HBase RPC机制与HMaster和HRegionServer进行通信: 与HMaster进行通信进行管理类操作: 与HRegionSe ...
- APOSE.Cell导入图片
一:读取EXcel单元格图片 1:读取全部单元格的图片集合 worksheet.pictureCollotion 2:遍历pictureCollotion (foreach (var pic ...