ConcreteStrategy上下文Context策略模式的UML类图
- 格式:ppt
- 大小:428.50 KB
- 文档页数:24
近来在看书实现GoF的23个设计模式,自己一点点地用建模工具按照自己的理解画出类图(是比较符合我个人思考理解的,个人觉得比通用类图更详细些),碰巧找到了一个挺好用的UML建模工具StarUML,也刚好从该软件中发现其实里面有默认的23个设计模式的通用类图,这就省去了我频繁地找书查看这些类图了,直接将它们保存为图片格式放到手机里面,是不是地就可以拿出来看看那,思考理解一下各个设计模式的原理,最后将它们记在脑里。
在此给出这些好用的类图与大家互相学习共同进步!
(按各个设计模式的英文名称的字典序排列)
Abstract Factory(抽象方法模式):
Adapter(适配器模式):
Bridge(桥接模式):
Builder(建造者模式):
Chain Of Responsibility(责任链模式):
Command(命令模式):
Composite(组合模式):
Decorator(装饰者模式):
Facade(门面模式):
Factory Method(工厂方法模式):
Flyweight(享元模式):
Interper(解释器模式):
Iterator(迭代器模式):
Mediator(中介者模式):
Memento(备忘录模式):
Observer(观察者模式):
Prototype(原型模式):
Proxy(代理模式):
Singleton(单例模式):
State(状态模式):
Strategy(策略模式):
Template Method(模板方法模式):
Visitor(访问者模式):。
23种设计模式UML 类图及对应示例代码(二)11.DoFactory.GangOfFour.Flyweight.StructuralFlyweight:运用共享技术有效的支持大量细粒度的对象。
享元模式:FLYWEIGHT在拳击比赛中指最轻量级。
享元模式以共享的方式高效的支持大量的细粒度对象。
享元模式能做到共享的关键是区分内蕴状态和外蕴状态。
内蕴状态存储在享元内部,不会随环境的改变而有所不同。
外蕴状态是随环境的改变而改变的。
外蕴状态不能影响内蕴状态,它们是相互独立的。
将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。
客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。
享元模式大幅度的降低内存中对象的数量。
Code12.DoFactory.GangOfFour.Interpreter.StructuralInterpreter:给定一个语言,定义它的文法的一种表示,并定义一个解释器用于解释特定文法。
解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。
客户端可以使用这个解释器来解释这个语言中的句子。
解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。
在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。
在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。
每一个命令对象都有一个解释方法,代表对命令对象的解释。
命令对象的等级结构中的对象的任何排列组合都是一个语言。
Code13.DoFactory.GangOfFour.Iterator.StructuralIterator:提供一种方法顺序访问一个聚合对象中的各种元素,而无需暴露该对象的内部表示。
迭代子模式:迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。
多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。
一.用例图用例模型是把应满足用户需求的基本功能(集) 聚合起来表示的强大工具。
用例模型的基本组成部件是用例角色和系统。
引入用例的主要目的是:确定系统应具备哪些功能这些功能是否满足系统的需求开发者与用户协商达成共识的东西为系统的功能提供清晰一致的描述,以便为后续的开发工作打下良好的交流基础,方便开发人员传递需求的功能为系统验证工作打下基础通过验证最终实现的系统能够执行的功能是否与最初需求的功能相一致保证系统的实用性从需求的功能用例出发提供跟踪进入系统中具体实现的类和方法检查其是否正确的能力特别是为复杂系统建模时常用用例模型构造系统的简化版本(也就是精化系统的变化和扩展能力使系统不要过于复杂)然后利用该用例模型跟踪对系统的设计和实现有影响的用例简化版本构造正确之后通过扩展完成复杂系统的建模图示用例图时既要画出三种模型元素,同时还要画出元素之间的各种关系(通用化关联依赖)用例代表的是一个完整的功能。
如何发现用例实际上从识别角色起发现用例的过程就已经已开始了对于已识别的角色通过询问下列问题就可发现用例●角色需要从系统中获得哪种功能角色需要做什么●角色需要读取产生删除修改或存储系统中的某种信息吗●系统中发生的事件需要通知角色吗或者角色需要通知系统某件事吗这些事件功能能干些什么●如果用系统的新功能处理角色的日常工作是简单化了还是提高了工作效率●还有一些与当前角色可能无关的问题也能帮助建模者发现用例例如●系统需要的输入/输出是什么信息这些输入/输出信息从哪儿来到哪儿去●系统当前的这种实现方法要解决的问题是什么也许是用自动系统代替手工操作UML 中的用例UML 中的用例用椭圆形表示用例的名字写在椭圆的内部或下方用例位于系统边界的内部角色与用例之间的关联关系或通信关联关系用一条直线表示用例和角色之间有连接关系用例和角色之间的关系属于关联association 又称作通信关联communication association,这种关联表明哪种角色能与该用例通信,关联关系是双向的一对一关系,即角色可以与用例通信,用例也可以与角色通信。
⼤话设计模式——C++版本⼀、什么是设计模式设计模式(Design pattern)是⼀套被反复使⽤、多数⼈知晓的、经过分类编⽬的、代码设计经验的总结。
使⽤设计模式是为了可重⽤代码、让代码更容易被他⼈理解、保证代码可靠性。
毫⽆疑问,设计模式于⼰于他⼈于系统都是多赢的,设计模式使代码编制真正⼯程化,设计模式是软件⼯程的基⽯,如同⼤厦的⼀块块砖⽯⼀样。
项⽬中合理的运⽤设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每⼀个模式描述了⼀个在我们周围不断重复发⽣的问题,以及该问题的核⼼解决⽅案,这也是它能被⼴泛应⽤的原因。
简单说:模式:在某些场景下,针对某类问题的某种通⽤的解决⽅案。
场景:项⽬所在的环境问题:约束条件,项⽬⽬标等解决⽅案:通⽤、可复⽤的设计,解决约束达到⽬标。
⼆、设计模式的三个分类创建型模式:对象实例化的模式,创建型模式⽤于解耦对象的实例化过程。
结构型模式:把类或对象结合在⼀起形成⼀个更⼤的结构。
⾏为型模式:类和对象如何交互,及划分责任和算法。
如下图所⽰:三、各分类中模式的关键点四、概说23种设计模式1.单例模式单例模式,它的定义就是确保某⼀个类只有⼀个实例,并且提供⼀个全局访问点。
单例模式具备典型的3个特点:1、只有⼀个实例。
2、⾃我实例化。
3、提供全局访问点。
因此当系统中只需要⼀个实例对象或者系统中只允许⼀个公共访问点,除了这个公共访问点外,不能通过其他访问点访问该实例时,可以使⽤单例模式。
单例模式的主要优点就是节约系统资源、提⾼了系统效率,同时也能够严格控制客户对它的访问。
也许就是因为系统中只有⼀个实例,这样就导致了单例类的职责过重,违背了“单⼀职责原则”,同时也没有抽象类,所以扩展起来有⼀定的困难。
其UML结构图⾮常简单,就只有⼀个类,如下图:2.⼯⼚⽅法模式作为抽象⼯⼚模式的孪⽣兄弟,⼯⼚⽅法模式定义了⼀个创建对象的接⼝,但由⼦类决定要实例化的类是哪⼀个,也就是说⼯⼚⽅法模式让实例化推迟到⼦类。
【黑马程序员济南】策略设计模式上一次我们聊了简单工厂模式,让大家了解到了如何使程序具备更高的解耦性,使每一个功能代码都独立出来,今天我们和大家聊一下另一种解耦的设计模式,它就是策略设计模式。
什么是策略设计模式:它定义了算法家族,分别封装起来,让他们之间可以项目替换,此模式让算法的变化,不会影响到算法的客户。
我们可以这样理解,工厂模式是让我们内部的构造变得高内聚低耦合,而策略模式是让我们的内部代码和外部客户端代码不直接进行联系,而是通过一个桥梁来进行沟通,并且使相同算法或功能的代码进行封装。
给大家用UML图大家通过上方的UML图可以看出,策略设计模式的思想为封装算法类,通过一个上下文的类,来沟通客户端和服务器端的逻辑代码。
给大家代码演示一下:/*** 此类为抽象的基类,用于具体的代码来继承使用* @author zhe**/publicabstractclass StragerySuper {//算法方法,用于具体的逻辑算法来实现publicabstractvoid AlphInterfact();}具体的实现代码类:/***具体的算法实现代码A***/class ConcreteA extends StragerySuper{@Overridepublicvoid AlphInterfact() {System.out.print("算法A的实现类");}}/***具体的算法实现代码B***/class ConcreteB extends StragerySuper{@Overridepublicvoid AlphInterfact() {System.out.print("算法B的实现类");}}/***具体的算法实现代码C***/class ConcreteC extends StragerySuper{@Overridepublicvoid AlphInterfact() {System.out.print("算法c的实现类");}}上下文类,作为连接客户端和后台代码端的桥梁/***Context类,用于和外界进行联系的类,用来对StrategySuper的引用***/class Context{StragerySuper stragerySuper;public Context(StragerySuper stragerySuper){//初始化构造函数,传递具体的策略对象this.stragerySuper = stragerySuper;}//上下文接口,根据具体的策略对象,调用其算法的方法,执行具体的逻辑方法publicvoid ContextInterface(){stragerySuper.AlphInterfact();}}客户端代码:/***客户端代码,通过Context中间类,来实现对具体实现类的调用**/class Client{Context context;publicvoid main(){//客户端通过context执行具体的逻辑代码context = new Context(new ConcreteA());context.ContextInterface();context = new Context(new ConcreteB());context.ContextInterface();context = new Context(new ConcreteC());context.ContextInterface();}}大家看策略模式是不是和简单工厂模式有点雷同,下一次我们把两个设计模式结合起来去实现,大家会发现我们的代码会更简洁和高效,每一种设计模式不是独立,他们都是可以交叉使用的。
策略模式(c++实现)策略模式策略模式(Startegy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使⽤算法的客户。
策略模式是⼀种定义⼀系列算法的⽅法,从概念上来看,所有这些算法完成的都是相同的⼯作,只是实现不同,它可以以相同的⽅式调⽤所有的算法,减少了各种算法类与使⽤算法类之间的耦合。
优点:1. 策略模式的strategy类层次为Context定义了⼀系列可供重⽤的算法或⾏为。
继承有助于析取出这些算法中的公共功能。
2. 简化了单元测试,因为每个算法都有⾃⼰的类,可以通过⾃⼰的接⼝单独测试。
⼴义作⽤:策略模式就是⽤来封装算法的,但在实践中,我们发现可以⽤他来封装⼏乎任何类型的规则,只要在分析过程中听到需要在不同时间应⽤不同的业务规则,就可以考虑使⽤策略模式处理这种变化的可能性。
与简单⼯⼚模式结合:在基本的策略模式中,选择所⽤具体实现的职责由客户端对象承担,并转给策略模式的Context对象。
这个本⾝并没有解除客户端需要选择判断的压⼒,⽽策略模式与简单⼯⼚模式结合后,选择具体实现的职责也可以由Context承担,这就是最⼤化的减轻了客户端的职责。
任何需求的变更都是需要成本的。
UML类图如下:代码如下:strategy.hclass Strategy{public:Strategy();virtual ~Strategy();virtual double getResult(double price) {return 0;};};context.h#include <string>#include "strategy.h"class Context{public:Context(std::string strName);double getResult(double cash);private:Strategy* m_Strategy;};context.cpp#include "context.h"#include "Common.h"Context::Context(std::string strName){if ("dis" == strName) {m_Strategy = new CashRebate(0.8);}else if("return" == strName){m_Strategy = new CashReturn(200, 100);}else if("nor" == strName){m_Strategy = new CashNormal();}}double Context::getResult(double cash){if(m_Strategy)return m_Strategy->getResult(cash);}common.h#include "strategy.h"#include "cashnormal.h"#include "cashrebate.h"#include "cashreturn.h"cashnormal.h#include "strategy.h"class CashNormal : public Strategy{public:CashNormal();double getResult(double price) override;};cashnormal.cpp#include "cashnormal.h"#include <assert.h>CashNormal::CashNormal(){}double CashNormal::getResult(double price){assert(price > 0);return price;}cashrebate.h#include "strategy.h"class CashRebate : public Strategy{public:CashRebate(double rebate);double getResult(double price) override; private:double m_Rebate;};cashrebate.cpp#include "cashrebate.h"#include <assert.h>CashRebate::CashRebate(double rebate): m_Rebate(rebate){}double CashRebate::getResult(double price){assert(price > 0);return price * m_Rebate;}cashreturn.h#include "strategy.h"class CashReturn : public Strategy{public:CashReturn(double condition, double returnNum); double getResult(double price) override; private:double m_Condition;double m_RetunNum;};cashreturn.cpp#include "cashreturn.h"CashReturn::CashReturn(double condition, double returnNum):m_Condition(condition), m_RetunNum(returnNum){}double CashReturn::getResult(double price){if(price >= m_Condition)return price - m_RetunNum;elsereturn price;}main.cpp#include <iostream>#include <iostream>#include <memory>#include "context.h"using namespace std;int main(){std::string input;std::cout << "select promotions:" << std::endl;std::cin >> input;Context cn(input);double res = cn.getResult(1000);std::cout << "result is :" << res << std::endl;return 0;}main函数⾥⾯通过输⼊来选择优惠的策略,context类通过输⼊使⽤简单⼯⼚模式创建对应的类。
设计模式中的多态——策略模式详解⽬录策略模式和java语⾔的多态特性有些像。
java的多态特性允许我们⾯向接⼝编程,不⽤关⼼接⼝的具体实现。
接⼝所指向的实现类,以及通过接⼝调⽤的⽅法的具体⾏为可以到运⾏时才绑定。
这么做最⼤的好处是在尽可能实现代码复⽤的前提下更好地应对具体实现类的变化。
⽐如我想增加⼀种接⼝的实现或者修改原有实现类的某个⾏为,那我⼏乎不⽤修改任何客户端代码。
策略模式可以说正是这种思想在设计模式上的运⽤。
它可以使我们更好的复⽤代码,同时使程序结构设计更有弹性,更好的应对变化。
2. 策略模式详解2.1 策略模式定义策略模式定义了⼀系列算法,并将每⼀个算法封装起来,⽽且使它们还可以相互替换。
策略模式让算法独⽴于使⽤它的客户端⽽独⽴的变化。
可以使⽤多态进⾏类⽐来理解策略模式的定义。
⼀系列算法可以理解成接⼝的不同实现类,因为不同实现类都实现了相同的接⼝,因⽽它们也可以相互替换。
策略模式让算法独⽴于客户端⽽变化与接⼝的实现类可以独⽴于使⽤接⼝的客户端变化类似。
2.2 策略模式的UML类图从UML类图上可以看出,策略模式中主要有3个⾓⾊抽象策略接⼝上图中的Strategy即抽象策略接⼝,接⼝中定义了抽象的策略算法algorithm()。
具体的策略实现类上图中的StrategyA和StrategyB即具体的策略实现。
不同的策略实现类都实现了抽象策略接⼝,并重写了其抽象策略⽅法。
因为都实现了相同的策略接⼝,因⽽算法可以相互替换,并且可以动态的改变具体的算法实现。
封装策略的上下⽂环境上图中的Context即策略的上下⽂环境。
它屏蔽了⾼层模块对策略算法的直接访问,封装了可能存在的变化。
⽽且提供了修改Strategy的setter⽅法,可以动态的改变算法的具体实现。
3.策略模式的优点我们可以结合使⽤策略模式的例⼦并与其它实现⽅案进⾏对⽐来看看策略模式到底有什么好处3.1 ⼀个使⽤策略模式的例⼦定义⼀个汽车类Car。
【设计模式】策略模式与状态模式。
策略模式与状态模式在实现上有共同之处,都是把不同的情形抽象为统⼀的接⼝来实现,就放在⼀起进⾏记录。
2个模式的UML建模图基本相似,区别在于状态模式需要在⼦类实现与context相关的⼀个状态⾏为。
状态模式的的思想是,状态之间的切换,在状态A执⾏完毕后⾃⼰控制状态指向状态B。
状态模式是不停的切换状态执⾏。
策略模式的思想上是,考虑多种不同的业务规则将不同的算法封装起来,便于调⽤者选择调⽤。
策略模式只是条件选择执⾏⼀次。
策略模式1. Strategy: 定义所有⽀持的算法的公共接⼝抽象类.2. ConcreteStrategy: 封装了具体的算法或⾏为,继承于Strategy3. Context: ⽤⼀个ConcreteStrategy来配置,维护⼀个对Strategy对象的引⽤。
状态模式1. State: 抽象状态类,定义⼀个接⼝以封装与context的⼀个状态相关的⾏为2. ConcreteState: 具体状态,每⼀⼦类实现⼀个与Context的⼀个状态相关的⾏为3. Context: 维护⼀个ConcreteState⼦类的实例,这个实例定义当前的状态。
使⽤场景: 状态模式主要解决的是当控制⼀个对象状态转换的条件表达式过于复杂时的情况。
把状态的判断逻辑转移到表⽰不同状态的⼀系列类当中,可以把复杂的判断逻辑简化。
当⼀个对象的⾏为取决于它的状态,并且它必须在运⾏时刻根据状态改变它的⾏为时,就可以考虑使⽤状态模式了。
策略模式的Strategy类层次为Context定义了⼀系列的可供重⽤的算法或⾏为。
继承有助于析取出这些算法中的公共功能。
在实践中,我们发现可以⽤它来封装⼏乎任何类型的规则,只要在分析过程中听到需要在不同时间应⽤不同的业务规则,就可以考虑使⽤策略模式处理这种变化的可能性。
状态模式和策略模式的⽐较 两个模式的实现类图虽然⼀致,但是实现⽬的不⼀样! ⾸先知道,策略模式是⼀个接⼝的应⽤案例,⼀个很重要的设计模式,简单易⽤,策略模式⼀般⽤于单个算法的替换,客户端事先必须知道所有的可替换策略,由客户端去指定环境类需要哪个策略,注意通常都只有⼀个最恰当的策略(算法)被选择。