设计模式之策略模式课件(PPT 45张)
设计模式之策略模式

前言:从很多方面来看,本课程实际上是在复述我自己学习和使用设计模式的经历,同很多大师一样,先掌握模式本身,再学习模式背后的思想,然后,又将这种理解扩展、延伸、复用、改进……但是现在回想起来,我发现自己那时大多都是遵循大多数前辈的建议行事,但并未理解面向对象的设计全部威力,直到开始学习设计模式,我们的面向对象设计能力才得以扩展和加强。
一开始就不可收拾,对设计模式着了迷,很喜欢研究别人的模式,很喜欢分析和比较,因为只有分析和比较才能领悟出新的东西,在叹服别人思想的闪光点的时候,自己也在思考。
同时,还注意到很多刚从事面向对象设计的人通过对设计模式的练习和领悟,写出的程序居然和大师级人物不相上下。
设计模式更多的展示了优秀的的面向对象设计实例,阐明了基本面向对象设计原则,而这些对于初学者更快设计出成熟的方案大有帮助。
一次又一次的思索,一次又一次的改进,我发现,使用思想作为武器,一段代码,写上20遍,收获是越来越多的,就像秦始皇统一六国的感觉,越来越美妙,妙不可言。
我已经完全相信:设计模式是面向对象发明以来在软件设计领域出现的最伟大的东西。
还有一个发现就是,一般专家容易建议先学习面向对象,打好基础,然后开始研究设计模式,但是在我的研究中,如同我研究设计模式一样,我惊讶的发现,在学习面向对象的同时,学习设计模式的学生,往往能够更好的适应工作要求,比仅仅学习面向对象的学生进步更快,而且,他们对面向对象设计模式的掌握从经验、熟练度上说几乎和老手一样(估计这也是很多老手反对的一个原因吧)。
课程对象:1.掌握C#基本语法的初学者2.想提升面向对象理解的学友3.想学习软件架构思想的工作者4.职业发展陷入瓶颈的大牛5.想掌握软件设计的思考者6.有思想、有准备的人7.想去大公司成功应聘的求职者8.想提升自己收入的白领9.想积累软件开发和设计经验的饿汉10.所有懂得欣赏面向对象思想的同仁课程安排:1.面向对象基础:从本质上告诉你什么叫封装、继承、多态,他们在内存的7个区域上是怎么分配的?语言本身做了些什么而编译器又做了些什么?这些编译后的IL语言各是什么含义?怎么认清他们的本质?从类到对象都经历了哪些复杂的过程?是不是也和婴儿一样经历了怀胎、分娩的过程?继承到底在内存上是怎么分配的?堆栈上的方法表是如何维护的?重载是如何区分的?晚绑定和编译时绑定的区别是什么?2、设计模式六大原则:开闭原则仅仅是对修改开放那么简单吗?职责单一原则这个职责单一的标准是什么?是功能?是业务?都不是……依赖倒置是怎么回事?聚合和组合以及继承到底该怎么用?里氏替换到底替换了谁?为什么要替换?3.单例方法模式:对系统说:“你是我的唯一”。
策略模式PPT课件

总结பைடு நூலகம்
• 在下面的情况下应当考虑使用策略模式: • 1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略
模式可以动态地让一个对象在许多行为中选择一种行为。 • 2. 一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具
体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法 类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只 持有一个数据类型是抽象算法类的对象。 • 3. 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及 到不必要接触到的复杂的和只与算法有关的数据。 • 4. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条 件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面, 就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。
策略模式的结构
• 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。 • 策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,
就是:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。"
第1页/共13页
策略模式(strategy)机构图
第3页/共13页
具体案例
• 下面的例子利用策略模式在排序对象中封装了不同的排序算法,这样以便允许客户端动态的替换排序策略 (包括Quicksort、Shellsort和Mergesort)。
第4页/共13页
抽象策略
• // "Strategy" abstract class SortStrategy { // Methods abstract public void Sort( ArrayList list ); }
策略模式

我可以把橡皮鸭类中的 fly()方法覆盖掉,就象覆盖 quack()的做法一样...
RubberDuck
quack(){ // 吱吱叫 } display(){ // 橡皮鸭 } fly(){ // 覆盖,变成什么事都不做 }
可是,以后用到诱饵 鸭(DecoyDuck)又会如何? 诱饵鸭是木头假鸭,不 会飞也不会叫...
设计模式之策略模式
2013.01
优秀的代码70%使用设计模式
——Michael
设计模式是什么呢?
• A design pattern is a general repeatable solution to a commonly occurring problem in software design.
假设有一个抽象类Animal,有两个具体的实现(Dog与Cat)继 承自Animal。
抽象超类可以是 抽象类或接口。 Animal
makeSound()
针对实现编程作法如下: Dog d = new Dog(); d.bark();
针对接口/超类型编程作法如下:
具体 实现
Animal animal = new Dog();
我们知道,并不是所有的鸭子都会飞、会 叫,所以继承不是正确的方法。但是虽然上面的 使用Flyable和Quackable接口的方法,可以解决 部分问题(不再有会飞的橡皮鸭子),但是这个解决 方案却彻底破坏了重用,它带来了另一个维护的 噩梦!而且还有一个问题我们前面没有提到,难 道所有的鸭子的飞行方式、叫声等行为都是一模 一样的吗?不可能吧!
客户使用封装 好的飞行和呱 呱叫算法族。
客户
Duck FlyBehavior flyBehavior QuackBehavior quackBehavior swim() display() performQuack() performFly() setFlyBehavior() setQuackBehavior() // 鸭子的其它方法
设计模式——策略模式

设计模式——策略模式⼀、定义与简单实现1、定义策略模式的定义包含三点:定义⼀类算法(接⼝)。
封装每个算法(实现类)。
这类算法的算法可互相替换(实现类之间可互相替换)。
2、UML类图前两点已经成了我们的职业习惯(项⽬中⼀般都是⼀接⼝对应⼀实现类),重点是要弄清楚后⾯的算法互相替换,这个替换是在哪⾥实现的,需要达到什么效果?下⾯是⼀个简单的策略模式的UML图。
定义⼀类算法(接⼝FlyBehavior)封装每个算法(实现类CanFly + NotFly)Duck中定义⼀个FlyBehavior变量,然后运⽤组合的⽅式,CanFly、NotFly可以互换定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独⽴于使⽤算法的客户,使Duck与Fly()解耦,运⽤的设计模式原则:封装变化多⽤组合,少⽤继承针对接⼝编程,不针对实现编程3、简单代码实现/** 飞翔⾏为*/public interface FlyBehavior {void fly();}public class CanFly implements FlyBehavior {@Overridepublic void fly() {System.out.println("I can fly!");}}public class NotFly implements FlyBehavior{@Overridepublic void fly() {System.out.println("I cant fly!");}}/** 叫声*/public interface QuackBehavior {void quack();}public class GaGa implements QuackBehavior{@Overridepublic void quack() {System.out.println("ga ga ...");}}public class GuaGua implements QuackBehavior {@Overridepublic void quack() {System.out.println("gua gua ...");}}public class NotQuack implements QuackBehavior {@Overridepublic void quack() {System.out.println("...... ??");}}/** 鸭⼦*/public interface DuckInterface {void swim();void display();void performFly();void performQuack();void setFlyBehavior(FlyBehavior flyBehavior);void setQuackBehavior(QuackBehavior quackBehavior); }public class Duck implements DuckInterface {private FlyBehavior flyBehavior;private QuackBehavior quackBehavior;@Overridepublic void swim() {System.out.println("I am swimming!");}@Overridepublic void display() {System.out.println("I have white feathers!");}@Overridepublic void performFly() {if (flyBehavior == null){System.out.println("no flyBehavior!");return;}flyBehavior.fly();}@Overridepublic void performQuack() {if (quackBehavior == null){System.out.println("no quackBehavior!");return;}quackBehavior.quack();}@Overridepublic void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}@Overridepublic void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}}public class Main {public static void main(String[] args) {FlyBehavior canFly = new CanFly();FlyBehavior notFly = new NotFly();//⼀个会飞的鸭⼦DuckInterface duck = new Duck();duck.setFlyBehavior(canFly);duck.performFly();//现在翅膀断了duck.setFlyBehavior(notFly);duck.performFly();}}⼆、框架中的策略模式框架中实现最明显的就是Mybatis中的执⾏器Executor,UML图虽然与给出的标准的策略模式UML有所差异,但是实现的效果⼀致。
设计模式之策略模式(Strategy)详解及代码示例

设计模式之策略模式(Strategy)详解及代码⽰例⼀、策略模式的定义 策略(Strategy)模式的定义:该模式定义了⼀系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使⽤算法的客户。
策略模式属于对象⾏为模式,它通过对算法进⾏封装,把使⽤算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进⾏管理。
⼆、策略模式优缺点 策略模式的主要优点如下。
多重条件语句不易维护,⽽使⽤策略模式可以避免使⽤多重条件转移语句。
符合开闭原则,可以在不修改原代码的情况下,灵活增加新算法。
算法使⽤和实现隔离分离,提⾼算法的保密性和安全性。
策略模式提供了⼀系列的可供重⽤的算法族,恰当使⽤继承可以把算法族的公共代码转移到⽗类⾥⾯,从⽽避免重复的代码。
策略模式可以提供相同⾏为的不同实现,客户可以根据不同时间或空间要求选择不同的。
其主要缺点如下。
客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
策略模式造成很多的策略类。
三、策略模式的结构与实现 策略模式是准备⼀组算法,并将这组算法封装到⼀系列的策略类⾥⾯,作为⼀个抽象策略类的⼦类。
策略模式的重⼼不是如何实现算法,⽽是如何组织这些算法,从⽽让程序结构更加灵活,具有更好的维护性和扩展性,现在我们来分析其基本结构和实现⽅法。
策略模式的主要⾓⾊如下。
抽象策略(Strategy)类:定义了⼀个公共接⼝,各种不同的算法以不同的⽅式实现这个接⼝,环境⾓⾊使⽤这个接⼝调⽤不同的算法,⼀般使⽤接⼝或抽象类实现。
具体策略(Concrete Strategy)类:实现了抽象策略定义的接⼝,提供具体的算法实现。
环境(Context)类:持有⼀个策略类的引⽤,最终给客户端调⽤。
其结构图如图所⽰: 代码实现如下:public class StrategyPattern{public static void main(String[] args){Context c=new Context();Strategy s=new ConcreteStrategyA();c.setStrategy(s);c.strategyMethod();System.out.println("-----------------");s=new ConcreteStrategyB();c.setStrategy(s);c.strategyMethod();}}//抽象策略类interface Strategy{public void strategyMethod(); //策略⽅法}//具体策略类Aclass ConcreteStrategyA implements Strategy{public void strategyMethod(){System.out.println("具体策略A的策略⽅法被访问!");}}//具体策略类Bclass ConcreteStrategyB implements Strategy{public void strategyMethod(){System.out.println("具体策略B的策略⽅法被访问!");}}//环境类class Context{private Strategy strategy;public Strategy getStrategy(){return strategy;}public void setStrategy(Strategy strategy){this.strategy=strategy;}public void strategyMethod(){strategy.strategyMethod();}} 测试结果如下:具体策略A的策略⽅法被访问!-----------------具体策略B的策略⽅法被访问! 如下补充⼀个促销策略模式:interface PromotionStrategy {void doPromotion();}class FanXianPromotionStrategy implements PromotionStrategy{@Overridepublic void doPromotion() {System.out.println("返现促销");}}class LiJianPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("⽴减促销");}}class ManJianPromotionStrategy implements PromotionStrategy{@Overridepublic void doPromotion() {System.out.println("满减促销");}}class PromotionActivity {private PromotionStrategy promotionStrategy;public PromotionActivity(PromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}public void executePromotionStrategy(){promotionStrategy.doPromotion();}}public class Test {public static void main(String[] args) {PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy());PromotionActivity promotionActivity1111 = new PromotionActivity(new FanXianPromotionStrategy());promotionActivity618.executePromotionStrategy();promotionActivity1111.executePromotionStrategy();}}四、策略模式的应⽤场景 策略模式在很多地⽅⽤到,如 Java SE 中的容器布局管理就是⼀个典型的实例,Java SE 中的每个容器都存在多种布局供⽤户选择。
设计模式之禅

第二部分 真刀实枪——23种设计模式完美演绎
21 组合模式
22.1 韩非子身边的卧底是 谁派来的
22.3 观察者模式的应用
22.5 最佳实践
22.2 观察者模式的定义 22.4 观察者模式的扩展
第二部分 真刀实枪——23种设计模式完美演绎
22 观察者模式
第二部分 真刀 实枪——23 种设计模式完 美演绎
8 工厂方法模式
第二部分 真刀实 枪——23种设计 模式完美演绎
9 抽象工厂模式
01
9.1 女娲的 失误
03
9.3 抽象工 厂模式的应
用
02
9.2 抽象工 厂模式的定
义
04
9.4 最佳实 践
第二部分 真刀实枪——23种设计模式完美演绎
0
0
1
2
10.1 辉煌
10.2 模板
工程——
方法模式
制造悍马
的定义
1 单一职责原则
第一部分 大 旗不挥,谁 敢冲锋—— 6大设计原 则全新解读
2 里氏替换原则
2.2 纠纷不 断,规则压 制
2.1 爱恨纠 葛的父子关 系
2.3 最佳实 践
第一部分 大旗不挥, 谁敢冲锋——6大 设计原则全新解读
3 依赖倒置原则
3.1 依赖倒置 原则的定义
3.3 依赖的三 种写法
7.1 我是 皇帝我独
苗
7.2 单例 模式的定
义
7.3 单例 模式的应
用
7.4 单例 模式的扩
展
7.5 最 佳实践
7 单例模式
8.1 女 娲造人 的故事
8.2 工厂 方法模式 的定义
8.3 工厂 方法模式 的应用
设计模式之策略模式与模板模式

PPT文档演模板
设计模式之策略模式与模板模式
定义和角色 结构示意图
实例说明 优缺点和环境
区别与联系
缺点 (1)每个不同的实现都需要定义一个 子类,这会导致类的个数的增加,也会增 加很多具体方法的数量,使设计更加抽象。 (2)如果选用的实现方式不当,复用 情况会很差。
PPT文档演模板
设计模式之策略模式与模板模式
定义和角色 结构示意图
示例代码 实例说明 优缺点和环境
PPT文档演模板
设计模式之策略模式与模板模式
定义和角色 结构示意图
示例代码 实例说明 优缺点和环境
写个客户端来测试运行一下,示例代码如下:
PPT文档演模板
设计模式之策略模式与模板模式
目录
Contents
PPT文档演模板
1 定义和角色 2 结构示意图 3 示例代码 4 实例说明 5 优缺点和环境
设计模式之策略模式与模板模式
定义和角色 结构示意图
实例说明 优缺点和环境
区别与联系
PPT文档演模板
创建一个咖啡类(Coffee)和茶(Tea)类,都继承Beverage 抽象类,而各个方法的具体实现方式都不同
这就实现了模板方法中最重要的 类的继承和方法的复用
设计模式之策略模式与模板模式
定义和角色 结构示意图
PPT文档演模板
设计模式之策略模式与模板模式
定义和角色 结构示意图
实例说明 优缺点和环境
区别与联系
方法(两种):
模板方法:
一个模板方法是定义在抽象类中的,把基本操作方法组合 在一起形成一个总算法或一个总行为的方法。一个抽象类可以 有任意多个模板方法,而不限于一个。每一个模板方法都可以 调用任意多个具体方法。
策略模式课件

w 算法的实现和使用算法的对象紧紧耦合在一起,使新增 算法或修改算法变得十分困难,系统应对变化的能力很 差。
第3页,共15页。
3.1 问题描述
方法
w 依据面向对象的思想,我们所能想到的办法就是将每 种算法的实现都剥离出来构成一个个独立的算法对象, 再从这些算法对象中抽象出公共的算法接口,最后将 算法接口组合到使用算法的类中。上述思路就引入了 一个新的设计模式-策略模式。
第4页,共15页。
3.2 典型案例
超市打折收银软件
为提高超市收益,超市开展促销活动。除了正常收费方式
外,添加对某些产品打折收费和满额返现收费方式。例如:
商品打8折、打7折、满300元消费返回100元、满500返 200……。实现能够计算总收费额度的功能。
如何添加和修改各 式各样的多种收费
方式?
第5页,共15页。
public CashRebate(double _discount)
{ discount = _discount;
}
public override double AcceptCash(double cash) {
return cash * discount; }
}
第8页,共15页。
3.2 典型案例
{ int nPoint = 101; double w = ((Panel)sender).Width - 1; double h = ((Panel)sender).Height - 1;
Point[] points = new Point[nPoint]; for (int i = 0; i < nPoint; i++)
简说设计模式——策略模式

简说设计模式——策略模式⼀、什么是策略模式 策略这个词应该怎么理解,打个⽐⽅说,我们出门的时候会选择不同的出⾏⽅式,⽐如骑⾃⾏车、坐公交、坐⽕车、坐飞机、坐⽕箭等等,这些出⾏⽅式,每⼀种都是⼀个策略。
再⽐如我们去逛商场,商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进⾏促销,说到底都是⼀些算法,这些算法本⾝只是⼀种策略,并且这些算法是随时都可能互相替换的,⽐如针对同⼀件商品,今天打⼋折、明天满100减30,这些策略间是可以互换的。
策略模式(Strategy ),定义了⼀组算法,将每个算法都封装起来,并且使它们之间可以互换。
UML结构图如下: 其中,Context 是上下⽂,⽤⼀个ConcreteStrategy 来配置,维护⼀个对Strategy 对象的引⽤;Strategy 是策略类,⽤于定义所有⽀持算法的公共接⼝;ConcreteStrategy 是具体策略类,封装了具体的算法或⾏为,继承于Strategy 。
1. Context 上下⽂ Context 上下⽂⾓⾊,也叫Context 封装⾓⾊,起承上启下的作⽤,屏蔽⾼层模块对策略、算法的直接访问,封装可能存在的变化。
2. 策略⾓⾊ 抽象策略⾓⾊,是对策略、算法家族的抽象,通常为接⼝,定义每个策略或算法必须具有的⽅法和属性。
algorithm 是“运算法则”的意思。
3. 具体策略⾓⾊ ⽤于实现抽象策略中的操作,即实现具体的算法,下⽅⽤print 代替。
测试类共3个ConcreteStrategy ,其它两个类与ConcreteStrategyA 同理,就不再赘述了。
1 public class Context {23 Strategy strategy;45 public Context(Strategy strategy) {6 this .strategy = strategy;7 }89 //上下⽂接⼝10 public void contextInterface() {11 strategy.algorithmInterface();12 }1314 }1 public abstract class Strategy {23 //算法⽅法4 public abstract void algorithmInterface();56 } 4. Client 客户端 下⾯依次更换策略,测试⼀下策略模式。
03策略模式(Strategy).ppt

定义抽象接口: abstract public class DiscountStrategy { abstract public double calculateDiscount(); } 定义三个具体实现的类: //百分比的折扣类(如书的价格20元,折扣7%则 20*7%=1.4 元 public class PercentageStrategy extends DiscountStrategy { private double percent = 0.0; private double price = 0.0; private int copies = 0; public PercentageStrategy(double price, int copies) { this.price = price; this.copies = copies; } public double getPercent() { return percent; } public void setPercent(double percent){ this.percent = percent; } public double calculateDiscount(){return copies * price * percent;}
Context public class Context {
Strategy stra; public Context(Strategy stra) { this.stra = stra; } public void doMethod() { stra.method(); }
}
客户端 public class Test {
例子
每年在新生入学时,由于本科生、硕士生和 博士生,他们助学金额的计算方法不同。请 编写软件实现。 一般实现:用分支语句。
设计模式之==策略设计模式

设计模式之==策略设计模式⼀、什么是策略设计模式 策略设计模式(Strategy Pattern)定义了⼀系列的算法,并将每⼀个算法封装起来,⽽且使它们之间可以互相替换。
策略模式让算法的变化不会影响到使⽤算法的客户。
分析下定义,策略模式定义和封装了⼀系列的算法,它们是可以相互替换的,也就是说它们具有共性,⽽它们的共性就体现在策略接⼝的⾏为上,另外为了达到最后⼀句话的⽬的,也就是说让算法独⽴于使⽤它的客户⽽独⽴变化,我们需要让客户端依赖于策略接⼝。
⼆、策略设计模式结构图这个类图并不复杂,右边是策略接⼝以及它的实现类,左边会有⼀个上下⽂,这个上下⽂会拥有⼀个策略,⽽具体这个策略是哪⼀种,我们是可以随意替换的三、策略模式写法举例我们需要实现这样⼀个功能:我们需要对⼀批不同格式的⽂件进⾏处理⽂件类型有 mp4,avi,rmvb,不同格式的⽂件使⽤不同的⽂件解析器来解析⽂件⽂件类型可不⼀定只有这⼏种,随着业务的扩展会不断增加,⽐如 : txt, jpg,png等等下⾯,我们使⽤策略设计模式来实现这个功能:⾸先,先来定义⼀个⽂件类型的枚举和⾃定义的⼀个⽂件类,⽤于描述我们处理的⽂件类型public class MyFile {private FileType fileType;private String fileName;private String filePath;public MyFile(Builder builder) {this.fileType = builder.fileType;this.fileName = builder.fileName;this.filePath = builder.filePath;}public static Builder builder() {return new Builder();}public static class Builder {private FileType fileType;private String fileName;private String filePath;public Builder fileType(FileType fileType) {this.fileType = fileType;return this;}public Builder fileName(String fileName) {this.fileName = fileName;return this;}public Builder filePath(String filePath) {this.filePath = filePath;return this;}public MyFile build() {return new MyFile(this);}}public FileType getFileType() {return fileType;}public String getFileName() {return fileName;}public String getFilePath() {return filePath;}@Overridepublic String toString() {return "MyFile{" +"fileType=" + fileType +", fileName='" + fileName + '\'' +", filePath='" + filePath + '\'' +'}';}}MyFilepublic enum FileType {MP4,AVI,RMVB,PNG}FileType再来,定义策略接⼝,相当于结构图中的 Strategy 接⼝public interface IStrategy<T> {void parse(T t);}这⾥也可以不使⽤泛型,因为我们在前⾯定义了⽂件描述的类 MyFile然后,是三个具体的策略类,分别是 mp4,avi,rmvb 三种格式⽂件的解析器,相当于结构图中的 ConcreteStrategypublic class Mp4ParserStrategy implements IStrategy<MyFile> {@Overridepublic void parse(MyFile file) {System.out.println("Mp4ParserStrategy.parse file=" + file);}}Mp4ParserStrategypublic class AviParserStrategy implements IStrategy<MyFile> {@Overridepublic void parse(MyFile file) {System.out.println("AviParserStrategy.parse file=" + file);}}AviParserStrategypublic class RmvbParserStrategy implements IStrategy<MyFile> {@Overridepublic void parse(MyFile file) {System.out.println("RmvbParserStrategy.parse file=" + file);}}RmvbParserStrategy这⾥没有实现解析器的功能,只是进⾏了简单的描述再下来是上下⽂,⼜或者叫策略管理的类,相对于结构图中的 Contextpublic final class ParserStrategyManager {private final Map<FileType, IStrategy<MyFile>> strategyMap;private ParserStrategyManager() {this.strategyMap = Maps.newConcurrentMap();this.strategyMap.put(FileType.AVI, new AviParserStrategy());this.strategyMap.put(FileType.MP4, new Mp4ParserStrategy());this.strategyMap.put(FileType.RMVB, new RmvbParserStrategy());}public void doParser(MyFile file) {if (!strategyMap.containsKey(file.getFileType())) {throw new IllegalStateException("⽆法处理这种格式的⽂件");}this.strategyMap.get(file.getFileType()).parse(file);}private static class ClassHolder {private static final ParserStrategyManager INSTANCE = new ParserStrategyManager();}public static ParserStrategyManager getInstance() {return ClassHolder.INSTANCE;}}ParserStrategyManager在这个类中,我们将⽂件类型和策略解析器以 Key,Value的形式存⼊⼀个Map当中,这样客户端在调⽤时只需传⼊⽂件的相关属性(包括⽂件类型),我们就根据⽂件类型找到⽂件对应的解析器进⾏解析,后续如果增加了其他的⽂件类型,只需要在 FileType 中增加类型并且增加具体的解析策略类,最后在 ParserStrategyManager 类中将⽂件类型和对应的解析策略类维护进 Map当中就可以了。
设计模式四:策略模式

设计模式四:策略模式策略模式所谓策略其实就是做⼀件事情有很多很多的⽅法,⽐如说⼀个商场要搞促销,促销的⽅式有可能有很多:打折啊,满100返50啊、积分等等之类的。
这种不同的促销⽅式在我们系统中表⽰就是⼀个⼀个的策略,并且策略是可以随时更换的,这个时候在设计系统时就可以使⽤策略模式。
商场有可能会更换或追加新的促销模式,也就是策略存在调整,也就是会更改以前的代码,为了满⾜开闭原则,这时就要使⽤抽象类和接⼝,这⾥我们偏向使⽤接⼝。
在接⼝⾥⾯定义策略的⽅法,根据不同的情况编写不同的实现类,实现不同的策略,策略模式⽐较适⽤于算法经常变化的情况,⽐如计算⼯资的⽅式、出⾏⽅式的选择等等。
如图所⽰,我们先定义策略的接⼝(Promotion),然后在这个策略接⼝⾥定义策略的⽅法(GetPrice()),接着我们定义了两种具体的策略(Discount打折)和(MoneyBack返现)。
策略模式会专门有⼀个上下⽂对象(PromotionContext)专门管理策略类,并且上下⽂对象和策略接⼝之间是聚合的关系,也就是整体和部分的关系,因此在上下⽂对象⾥应该保存⼀个促销类型的引⽤,另外上下⽂对象⾥⼀般会有⼀些⽅便客户端调⽤的⽅法,如GetPrice()。
客户端程序可以通过上下⽂对象得到价格,这个GetPrice()⾥会根据不同的策略,执⾏不同的策略⽅法。
如果客户端不想使⽤上下⽂中定义的默认的策略,也可以去修改策略类,因为上下⽂中有⼀个ChangePromotion()的⽅法,客户端主要使⽤上下⽂对象,如果需要修改策略,他还要依赖于具体的策略对象。
⽰例:1、策略接⼝:1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9/*10策略接⼝11*/12public interface IPromotion13 {14///<summary>15///根据原价和策略计算新价格16///</summary>17///<param name="originPrice">原价</param>18///<returns></returns>19double GetPrice(double originPrice);20 }21 }2、Discount打折策略类1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9///<summary>10///打折策略类11///</summary>12public class Discount :IPromotion13 {1415public double GetPrice(double originPrice)16 {17 Console.WriteLine("打⼋折:");18return originPrice * 0.8;19 }20 }21 }3、MoneyBack返现类1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9/*10返现策略类:满100返50的策略11*/12class MoneyBack :IPromotion13 {14public double GetPrice(double originPrice)15 {16 Console.WriteLine("满100返50");17return originPrice - (int)originPrice / 100 * 50;18 }19 }20 }4、策略上下⽂类1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9/*10策略上下⽂,为客户选择合适的策略11*/12public class PromotionContext13 {14private IPromotion p = null;1516public PromotionContext(IPromotion p)17 {18this.p = p;19 }2021public double GetPrice(double originPrice)22 {23// 默认策略24if (this.p == null)25 {26this.p = new Discount();27 }28return this.p.GetPrice(originPrice);29 }3031///<summary>32///更改策略的⽅法33///</summary>34///<param name="p"></param>35public void ChangePromotion(IPromotion p)36 {37this.p = p;38 }39 }40 }5、主程序调⽤1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace策略模式8 {9class Program10 {11static void Main(string[] args)12 {13// 默认策略:打⼋折的策略14 PromotionContext pc = new PromotionContext(null);15 Console.WriteLine(pc.GetPrice(200)) ;1617// 更改策略:满100返50的策略18 pc.ChangePromotion(new MoneyBack());19 Console.WriteLine(pc.GetPrice(155.9));20 Console.ReadKey();21 }22 }23 }代码连接地址:https:///files/dotnet261010/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.rar。
设计模式系列-策略模式

设计模式系列-策略模式今天下班回家,吃完晚饭后在⽹上闲逛,看了看电视剧《男⼈帮》的经典台词,感觉很经典,虽然这个电视剧我早已经在上个⽉就看完了,但是看了看⾥⾯的经典开场⽩和台词,还是不由⾃主的伸出⼤拇指,赞啊!列举部分台词如下:(1)⾃从我们睁开眼睛看这个世界的第⼀天起,我们看到的就只有两种⼈,男⼈和⼥⼈。
他们分属于两⼤不同的阵营,为了彻底收服对⽅,⼤家互相往死⾥掐。
(2)根据⼀个遥远的传说,说有⼀种东西叫爱情,可以彻底终结这场战争。
于是⼤家纷纷的赶紧去寻找,赶紧去幻想,找到头破⾎流才发现,原来这个感情也是另⼀些⼈在书房⾥炮制出来的。
于是⼤家更加绝望,更加痛苦,更加互相的往死⾥掐。
1、场景案例尤其是上⾯这⼏句,让我想起了我⼀同事(这⾥⽤“某某哥”代替)和他⼥朋友的故事(这⾥⽤“某某嫂”代替),⼀次活动中,某某哥认识了某某嫂,那个⼀见钟情呀,简直是看不见某某嫂就吃不下饭、写不下代码呀,在追求中也没少费⼯夫。
⽐如:送⼩礼物,请客吃饭,搞浪漫等等,我们就把这⼏个阶段分别⽤代码模拟⼀下把!①第⼀阶段赠送⼩礼物代码如下://第⼀阶段送⼩礼物public static void SendGift(){Console.WriteLine("送给⼥⽅精美⼩礼物!");}static void Main(string[] args){//第⼀阶段SendGift();}②此时、通过送精美⼩礼物⼥⽅已经愿意与男⽅接触,这时就可以⼀起吃饭了,代码如下://第⼀阶段送⼩礼物public static void SendGift(){Console.WriteLine("送给⼥⽅精美⼩礼物!");}//添加第⼆阶段请客吃饭public static void Eat(){Console.WriteLine("请⼥⽣吃⽜排!");}static void Main(string[] args){//第⼀阶段//SendGift(); //此时第⼀阶段已经不需要了所以注销掉进⼊第⼆阶段//第⼆阶段Eat();}③经过之前阶段的接触,两⼈已经在⼀起了,在⼀起就免不了在热恋中经历浪漫情节,第三阶段:制造浪漫、代码如下://第⼀阶段送⼩礼物public static void SendGift(){Console.WriteLine("送给⼥⽅精美⼩礼物!");}//添加第⼆阶段请客吃饭public static void Eat(){Console.WriteLine("请⼥⽣吃⽜排!");}//添加第三阶段浪漫:烛光晚餐等待⼥友public static void Romantic(){Console.WriteLine("精⼼制作了红酒、晚餐与蜡烛,等待⼥友回家!");}static void Main(string[] args){//第⼀阶段//SendGift(); //此时第⼀阶段已经不需要了所以注销掉进⼊第⼆阶段//第⼆阶段//Eat(); //此时第⼆阶段也已经经过,所以注销掉、进⼊第三阶段//第三阶段Romantic();}看了某某哥追某某嫂的经过后,我们会发现,每当进⼊⼀个新阶段的时候,我们就需要去修改我们的代码,加⼊新的追⼥策略,并且将main函数中的调⽤修改成进⼊新的阶段,那么我们怎么样能避免,在进⼊新阶段后不去修改调⽤的代码呢?当然这个肯定难不倒你,代码如下://第⼀阶段送⼩礼物public static void SendGift(){Console.WriteLine("送给⼥⽅精美⼩礼物!");}//添加第⼆阶段请客吃饭public static void Eat(){Console.WriteLine("请⼥⽣吃⽜排!");}//添加第三阶段浪漫:烛光晚餐等待⼥友public static void Romantic(){Console.WriteLine("精⼼制作了红酒、晚餐与蜡烛,等待⼥友回家!");}static void Main(string[] args){Console.Write("现在是第⼏阶段?:");string level = Console.ReadLine(); //代表当前是哪个阶段switch (level){case"one"://第⼀阶段SendGift();break;case"two"://第⼆阶段Eat();break;case"three": //第三阶段Romantic();break;default:Console.WriteLine("没这个打算凑什么热闹?");break;}}这样我们就解决了在两⼈进⼊新的阶段后,⽆需修改main⽅法中的代码!输出结果如下:那么如果这时两⼈已经到了谈婚论嫁的时候,该怎么办呢?也就是要在新加⼊⼀个阶段叫做结婚呢?2、引⼊策略模式普通的办法还是要去新增⽅法,在修改调⽤代码!那我们有没有办法呢?别着急,先看看策略模式、定义如下:“它定义了算法家族,分别封装起来,让他们之间可以互相替换,次模式让算法的变化,不会影响到使⽤算法的客户”。
设计模式之策略模式(StrategyPattern)

设计模式之策略模式(StrategyPattern)策略模式(Strategy Pattern)1.场景引⼊⼤家外出旅游时肯定要事先规划⾏程,那乘坐的交通⼯具便是不得不考虑的问题。
我们出门时会有好多交通⼯具作为候选,⽐如公交、飞机、⽕车、步⾏、脚踏车等等。
再⽐如,计算1+1时,我们可以选择珠⼼算、计算器、列竖式等等来解决。
上述公交、飞机、⽕车、步⾏、脚踏车便是出⾏⽅式的多种策略(⽅法),同样珠⼼算、计算器、列竖式也是计算1+1=2的多种策略。
2.定义定义算法(策略)族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独⽴于使⽤算法的客户。
(来⾃于《Head First 设计模式》)稍微解释⼀下:主体对象(即上述图⽚中的⼈)可以有多种策略(即出⾏⽅式)。
主体对象可以根据环境或者条件的不同选择不同的策略来完成所需要的功能,但是如果将这些不同的策略都硬编码到⼀个类中,通过if…else…或者case等条件判断语句来进⾏选择,后果是代码耦合度过⼤,维护较为困难。
⽽策略模式的意图主要就是将主体对象(上述图⽚中的⼈)和策略尽可能地分离开来,将这些策略定义为单独的类(同时这些策略实现相同的接⼝)。
通过将策略对象组合进主题对象来达到解耦效果。
3.组成部分策略模式把对象本⾝和策略区分开来,因此该模式也分为两个部分:环境类(Context):⽤来操作策略的上下⽂环境,也就是⼈。
策略类:抽象策略类(Strategy):策略的抽象,也就各种出⾏⽅式的⽗类。
具体策略类(ConcreteStrategy):具体的策略实现,每⼀种具体的出⾏⽅式,如⾃⾏车、汽车等等。
4.具体实现现在我们按照上述组成部分来实现⼀个外出旅游选择出⾏⽅式的功能。
第⼀步:定义抽象策略接⼝/*** IVehicle.java* 交通⼯具-抽象策略接⼝* 包含⼀个出⾏⽅法goingOut()*/public interface IVehicle {void goingOut();}第⼆步:实现具体策略类/*** Bicycle.java* ⾃⾏车-具体策略类* 重写出⾏⽅法goingOut()*/public class Bicycle implements IVehicle {@Overridepublic void goingOut() {System.out.println("骑着⾃⾏车---哐哧哐哧。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目
录
1 2 3 4 5
• Contents
定义和角色
结构示意图
示例代码 实例说明 优缺点和环境
定义和角色
结构示意图 示例代码 实例说明 优缺点和环境
ContreteStrategyA +algorithmInterface():void
Context
-strategy:Strategy <create> +Context(aSteategy:Strategy) +contextInterface():void
设计模式之策略模式
主讲人 :成 玉 丹 间:2016.11.14
时
目
录
1
定义和角色 结构示意图 示例代码
实例说明
• Contents
2 3 4 5
优缺点环境
定义和角色
结构示意图 示例代码 实例说明 优缺点和环境
定义:
策略模式定义了一系列的算法,并将每一个
算法封装起来,而且使它们还可以互相替换。策 略模式让算法独立于使用它的客户而独立变化。
• Contents
定义和角色
结构示意图
示例代码 实例说明
优缺点和环境
1、策略接口:定义算法的接口:
定义和角色
结构示意图 示例代码 实例说明 优缺点和环境
/** *策略:定义算法的接口 */
public interface Strategy{ /** *某个算法的接口,可以有传入参数,也可以有返回值 */
<interface> Strategy +algorithmInterface():void
ContreteStrategyB +algorithmInterface():void
ContreteStrategyC +algorithmInterface():void
策略实现(算法实现)
目
录
1 2 3 4 5
目
录
1 2 3 4 5
• Contents
定义和角色
结构示意图
示例代码 实例说明 优缺点和环境
实例:报价管理问题
定义和角色
向客户报价,对于销售部门的人来讲,这是一个非常重
结构示意图 示例代码 实例说明 优缺点和环境
大、非常复杂的问题,对不同的客户要报不同的价格,例如 有新客户、老客户、大客户等。 为了演示的简洁性,假定现在需要实现一个简化的报价 管理,实现如下的功能: 1)对普通客户或者是新客户报全价
定义了计算价格 的算法
public double quote(double goodsPrice, String customerType){ if(customerType.equals("普通客户")){ System.out.println("对于普通客户或者是新客户,没有折扣"); return goodsPrice; }else if(customerType.equals("老客户")){ System.out.println("对于老客户,统一折扣 5%"); return goodsPrice * (1 - 0.05); }else if(customerType.equals("大客户")){ System.out.println("对于大客户,统一折扣 10%"); return goodsPrice * (1 - 0.1); } } 这种解决方案存在的问题:价格类包含了 //其余人员报原价 所有计算报价的算法,使得价格类,尤其 return goodsPrice; }
/** *实现具体的算法 */
public class ConcreteStrategyA implements Strategy{ /** *具体的算法实现 */
public void algorithmInterface(); }
3、上下文的实现Biblioteka 示例代码如下/** *上下文对象,通常会持有一个具体的策略对象 */ public class Context{ /** *持有一个具体的策略对象 */ private Strategy strategy; /** *构造方法,传入一个具体的策略对象 *@param aStrategy 具体的策略对象 */ public Context(Strategy aStrategy){ this.strategy = aStrategy; }
是报价这个方法比较庞杂,难以维护。
2、不用模式的修改方案:
把这些算法从报价方法里面拿出去,形成独立的方法。据 此写出如下的实现代码,示例代码如下:
定义和角色
结构示意图 示例代码 实例说明 优缺点和环境
角色(三种):
策略接口:用来约束一系列具体的策略算法。 策略实现:就是具体的算法实现。 上下文:负责和具体的策略类交互,通常上下文会持有一 个真正的策略实现。还可以让具体的策略类来获取上下文的数 据,甚至让具体的策略类来获取上下文的数据。
角色之间的关系:上下文使用策略接口来调用具体的策略 实现定义的算法。
2)对老客户报的价格,统一折扣5%
3)对大客户报的价格,统一折扣10% 该怎么实现呢?
1、不用模式的解决方案:
定义和角色
结构示意图 示例代码 实例说明 优缺点和环境
/** *价格管理,主要完成向客户所报价格的功能 */ public class Price{ /** *报价对不同类型的客户计算不同的价格 *@param goodsPrice 商品销售原价 *@param customerType 客户类型 *@return 计算出的应该给客户报的价格 */
public void algorithmInterface(); }
调用具体的算法
定义和角色
结构示意图 示例代码 实例说明 优缺点和环境
2、策略实现:在具体的算法实现中,定义了三个,分别 是ConcreteStrategyA、ConcreteStrategyB、 ConcreteStrategyC ,示例非常简单,由于没有具体算法 的实现,三者也就是名称不同,示例代码如下:
定义和角色
结构示意图 示例代码 实例说明 优缺点和环境
/** *上下文对客户端的操作接口,可以有参数和返回值 */ public void contextInterface(){ //通常会转调具体的策略对象进行算法计算 strategy.algorithmInterface(); } }
例如上文提到A,B,C 三个对象