设计模式之策略模式课件ppt(45张)
- 格式:ppt
- 大小:1.97 MB
- 文档页数:45
前言:从很多方面来看,本课程实际上是在复述我自己学习和使用设计模式的经历,同很多大师一样,先掌握模式本身,再学习模式背后的思想,然后,又将这种理解扩展、延伸、复用、改进……但是现在回想起来,我发现自己那时大多都是遵循大多数前辈的建议行事,但并未理解面向对象的设计全部威力,直到开始学习设计模式,我们的面向对象设计能力才得以扩展和加强。
一开始就不可收拾,对设计模式着了迷,很喜欢研究别人的模式,很喜欢分析和比较,因为只有分析和比较才能领悟出新的东西,在叹服别人思想的闪光点的时候,自己也在思考。
同时,还注意到很多刚从事面向对象设计的人通过对设计模式的练习和领悟,写出的程序居然和大师级人物不相上下。
设计模式更多的展示了优秀的的面向对象设计实例,阐明了基本面向对象设计原则,而这些对于初学者更快设计出成熟的方案大有帮助。
一次又一次的思索,一次又一次的改进,我发现,使用思想作为武器,一段代码,写上20遍,收获是越来越多的,就像秦始皇统一六国的感觉,越来越美妙,妙不可言。
我已经完全相信:设计模式是面向对象发明以来在软件设计领域出现的最伟大的东西。
还有一个发现就是,一般专家容易建议先学习面向对象,打好基础,然后开始研究设计模式,但是在我的研究中,如同我研究设计模式一样,我惊讶的发现,在学习面向对象的同时,学习设计模式的学生,往往能够更好的适应工作要求,比仅仅学习面向对象的学生进步更快,而且,他们对面向对象设计模式的掌握从经验、熟练度上说几乎和老手一样(估计这也是很多老手反对的一个原因吧)。
课程对象:1.掌握C#基本语法的初学者2.想提升面向对象理解的学友3.想学习软件架构思想的工作者4.职业发展陷入瓶颈的大牛5.想掌握软件设计的思考者6.有思想、有准备的人7.想去大公司成功应聘的求职者8.想提升自己收入的白领9.想积累软件开发和设计经验的饿汉10.所有懂得欣赏面向对象思想的同仁课程安排:1.面向对象基础:从本质上告诉你什么叫封装、继承、多态,他们在内存的7个区域上是怎么分配的?语言本身做了些什么而编译器又做了些什么?这些编译后的IL语言各是什么含义?怎么认清他们的本质?从类到对象都经历了哪些复杂的过程?是不是也和婴儿一样经历了怀胎、分娩的过程?继承到底在内存上是怎么分配的?堆栈上的方法表是如何维护的?重载是如何区分的?晚绑定和编译时绑定的区别是什么?2、设计模式六大原则:开闭原则仅仅是对修改开放那么简单吗?职责单一原则这个职责单一的标准是什么?是功能?是业务?都不是……依赖倒置是怎么回事?聚合和组合以及继承到底该怎么用?里氏替换到底替换了谁?为什么要替换?3.单例方法模式:对系统说:“你是我的唯一”。
设计模式之策略模式浅谈以及简单例⼦设计模式之策略模式策略模式定义了算法类,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独⽴于使⽤算法的客户。
策略模式是对算法的包装,是把使⽤的责任和算法本⾝分割开来,委派给不同的对象管理。
策略模式通常把⼀个系列的算法包装到⼀系列的策略类⾥⾯,作为⼀个抽象策略类的⼦类。
策略模式涉及到三个⾓⾊:环境(Context)⾓⾊:持有⼀个Strategy的引⽤,也称策略上下⽂。
抽象策略(Strategy)⾓⾊:这是⼀个抽象⾓⾊,通常使⽤抽象类或者接⼝来实现。
此⾓⾊给出所有的具体策略类所需要的接⼝。
具体策略(ConcreteStrategy)⾓⾊:此⾓⾊包装了所有的算法和⾏为。
Eg:商场搞促销,促销⽅式有打折、满100减50等。
在本例中,抽象策略⾓⾊⽤⼀个结果实现,接⼝中有⼀个计算价格的⽅法。
接⼝实现如下:1namespace Strategy_Pattern23 {45///<summary>67///策略接⼝89///</summary>1011interface IPromotion1213 {1415///<summary>1617///根据原价和策略计算新价格1819///</summary>2021///<param name="originalPrice">原价</param>2223///<returns></returns>2425double GetPrice(double originalPrice);2627 }2829 }具体策略⾓⾊有两个,分别表⽰打折类和满100减50,都实现策略接⼝。
打折类实现如下:1 using System;2345 namespace Strategy_Pattern67 {89 /// <summary>1011 /// 打折策略类1213 /// </summary>1415 class Discount : IPromotion1617 {181920212223 #region Public Methods2425 public double GetPrice(double originalPrice) 2627 {2829 Console.WriteLine("打⼋折");3031 return originalPrice * 0.8;3233 }3435 #endregion36373839 }4041 }满100减50类实现如下:/// <summary>/// 返现策略类:满100返50/// </summary>class MoneyBack : IPromotion{#region Public Methodspublic double GetPrice(double originalPrice){Console.WriteLine("满100返50");return originalPrice - (int)originalPrice / 100 - 50; }#endregion}环境(Context)⾓⾊类如下:/// <summary>/// 策略上下⽂类/// </summary>class PromotionContext{#region Fieldsprivate IPromotion m_promotion = null;#endregion#region Constructorspublic PromotionContext(IPromotion iPromotion){this.m_promotion = iPromotion;}#endregion#region Public Methods/// <summary>/// 默认策略⽅法/// </summary>/// <param name="originalPrice"></param>/// <returns></returns>public double GetPrice(double originalPrice){if (this.m_promotion == null){this.m_promotion = new Discount();}return this.m_promotion.GetPrice(originalPrice);}/// <summary>/// 更改策略的⽅法/// </summary>/// <param name="iPromotion"></param>public void ChangePromotion(IPromotion iPromotion){this.m_promotion = iPromotion;}#endregion}然后再主类中调⽤相应的策略,主类实现如下:class Program{static void Main(string[] args){//默认策略:打⼋折的策略PromotionContext promotionContext=new PromotionContext(null);Console.WriteLine(promotionContext.GetPrice(300));//更改策略:满100减50的策略promotionContext.ChangePromotion(new MoneyBack()); Console.WriteLine(promotionContext.GetPrice(100));Console.ReadLine();}}。
设计模式——策略模式⼀、定义与简单实现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)类:定义了⼀个公共接⼝,各种不同的算法以不同的⽅式实现这个接⼝,环境⾓⾊使⽤这个接⼝调⽤不同的算法,⼀般使⽤接⼝或抽象类实现。
具体策略(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 中的每个容器都存在多种布局供⽤户选择。
设计模式(⼀):策略模式 现实⽣活中,我们要做⼀件事情或者完成某项⼯作,往往有很多种途径。
⽐如我们出游,可以选择坐汽车,坐⽕车,⼟豪点的选择是坐飞机。
还有我们现在线下的⽀付⽅式也有了很多种选择,以前在外⾯忘了带钱的话可能⼀瓶⽔都难以买到,现在只要我们⼿机在⾝上,可以⽤微信或者⽀付宝。
在软件设计层⾯,我们把各种⽀付⽅式叫做策略。
如果不考虑设计模式的话,我们可能会在⼀个类中⽤if..else⽅式来选择⽀付⽅式,即if(type == 1){//微信⽀付}else if(type == 2){// ⽀付宝⽀付}else if(type == 3){//现⾦⽀付}但如果以后要改变⽀付⽅式,⽐如不能⽤微信⽀付了,或者新增了其他⽀付⽅式,我们就要改变这个类,这会带来代码维护的⿇烦。
.模式结构和定义 下图为策略模式的结构: 从图中我们看到,客户context拥有成员变量strategy(策略),⾄于需要⽤到那种策略,我们可以在构造器中指定。
策略模式的定义是:定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独⽴于使⽤算法的客户。
这算法体现了⼏个设计原则,第⼀、把变化的代码从不变的代码中分离出来;第⼆、针对接⼝编程⽽不是具体类(定义了策略接⼝);第三、多⽤组合,少⽤继承(客户通过组合⽅式使⽤策略)。
.应⽤实例 下⾯以公司职员的⼯作内容为例介绍策略模式 定义策略接⼝,就是⼯作内容interface DoWorking{public void comeOn();} 编码类实现策略接⼝DoWorkingclass Coding implements DoWorking{public void comeOn(){System.out.println("I'm coding....");}} 审计类实现策略接⼝DoWorkingclass auditing implements DoWorking{public void comeOn(){System.out.println("我正在审计财务报表....");}} 招聘类实现策略接⼝DoWorkingclass recruiting implements DoWorking{public void comeOn(){System.out.println("I'm recruting new employees...");}} 定义客户端职员类,其中包含成员变量doWorking(策略),以及开展⼯作的⽅法startWork() class Employee{public DoWorking doWorking;//组合的⽅式使⽤策略public void startWork(){eOn();}} 客户端程序员继承职员类class Coder extend Employee{public Coder(){doWorking = new Coding();//使⽤编码策略}} 测试程序员调⽤策略public class StrategyClient {public static void main(String[] args){Employee coder = new Coder();coder.startWork();}} 运⾏结果: I'm coding.... 1.优点 (1).体现了“对修改关闭,对扩展开放”原则,客户端增加⾏为不⽤修改原有代码,只要添加⼀种策略即可。
简说设计模式——策略模式⼀、什么是策略模式 策略这个词应该怎么理解,打个⽐⽅说,我们出门的时候会选择不同的出⾏⽅式,⽐如骑⾃⾏车、坐公交、坐⽕车、坐飞机、坐⽕箭等等,这些出⾏⽅式,每⼀种都是⼀个策略。
再⽐如我们去逛商场,商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进⾏促销,说到底都是⼀些算法,这些算法本⾝只是⼀种策略,并且这些算法是随时都可能互相替换的,⽐如针对同⼀件商品,今天打⼋折、明天满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 客户端 下⾯依次更换策略,测试⼀下策略模式。
设计模式四:策略模式策略模式所谓策略其实就是做⼀件事情有很多很多的⽅法,⽐如说⼀个商场要搞促销,促销的⽅式有可能有很多:打折啊,满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。