1.设计模式纵横谈之创建型模式
1.模式分类:
*从目的来看:(需要掌握)
-创建型模式:负责对象创建
-结构型模式:处理类与对象间的组合
-行为型模式:类与对象交互中的职责分配
*从范围来看:(需要了解)
-类模式处理类与子类的静态关系
-对象模式处理对象间的动态关系
2.单线程Singleton模式的基本动机:
满足一个类只有一个实例,并且这个实例具有全局访问权限。
【案例实现】 1:提供一个私有构造器,防止产生1个以上的实例。
2:再提供一个公有的只读的静态方法,用于获取该类的实例,有两种结果,如果有名为instance的实例,将返回该实例。如果没有名为instance的实例,将创建一个名为instance的实例。
【测试】:不能通过第1句来创建实例了,因为没有公有的构造方法了。
第2句用于创建该类的实例。
第3句因为已经创建过实例了,所以该句的作用是获取该类的实例。
第4句用于调用ReferenceEquals()方法来比较两个实例的引用是否是同一个,并向控制台输出比较结果。
3.单线程(Singleton)模式的要点:
*防止产生多个实例:
-提供私有(private)或(protected)级别的构造方法。
-不要支持ICloneable接口。
-不要支持序列化。
*单线程模式只考虑对象的创建,不考虑对象回收,因为在有垃圾回收的环境下,考虑垃圾回收意义不大。
*该模式不支持多线程,因为该模式可能会在多线程环境下产生多个实例,将违背该模式的基本动机。
4.【案例实现】 多线程环境下的单线程模式设计:
1.创建一个同步锁
2.当多线程的一个分支判断出实例为空时,立即上锁,再判断一下,才进行创建实例,防止违背单线程模式的初衷。
5.【案例实现】 静态构造器下的单线程模式,静态字段只在类加载时执行一次,以此来实现一个实例。下面是两种实现方式:
6.单线程模式扩展:
*将一个实例扩展到n个实例,例如对象池的实现。
*将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。
*理解和扩展单线程模式的核心是:“如何控制用户使用new对一个类的实例构造器的任意调用”。
7.创建型模式(主要解决new的问题)解决思路:
*封装变化点——哪里变化,就封装哪里
*潜台词——如果没有变化,当然不需要封装。
8.工厂模式是面向接口编程,依赖接口,变化点在“对象创建”,所以要封装“对象创建”。
9. 简单工厂模式的问题在于不能应对“不同系列对象”的变化。
【解决方案】使用面向对象的技术来“封装”变化点。
- 抽象工厂模式(Abstract Factory)的基本动机:不同系列相互依赖的对象的创建工作,避免紧耦度。
11.抽象工厂模式的要点:
*当有“多系列对象构建”的需求时,可以使用抽象工厂模式。
*抽象工厂模式只能添加新序列,并不能添加新对象。
*抽象工厂模式经常和Factory method一起使用,达到“对象创建”需求。
12.builder模式的基本动机:算法相对稳定,对象的各个部分剧烈变化。
13.builder模式的要点:
*当有“算法较稳定,对象的各个部分会经常变化”的需求时,使用builder模式。
*builder模式只对对象的各个部分进行改动,不能对算法进行改动。
*抽象工厂模式用于解决“系列对象“需求,builder模式用于解决“对象部分 ”的需求。builder模式通常和Composite模式组合使用。
14.设计模块的耦合关系:
*紧耦合:软件发生变化时,依赖该模块的相关模块都要更改
*松耦合:软件发生变化时,高层模块较稳定,只有一些低层模块需要被替换或更改。
注意:首先掌握软件的模块如何划分,其次才能使用设计模式。
15.工厂方法(Factory method)模式的基本动机:对象的具体实现经常发生变化,但拥有比较稳定的接口。
16.工厂方法模式的几个要点:
*隔离类对象的使用者和具体类型之间的耦合关系。
*采用面向对象的方法,将具体实现方法在子类中实现,从而达到扩展的目的。
*工厂方法模式解决的是“单个对象”的需求,抽象工厂模式解决的是“系列对象”的需求,Builder模式解决的是“对象部分”的需求。
17.依赖关系倒置:实现细节应依赖于抽象,一般做法抽象A依赖于抽象B,实现细节b依赖于抽象B。
18.原型模式(ProtoType):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
19.原型模式的使用场景:(原型模式比new新建对象性能要好)
*需要一个类实例化大量的重复对象,或者数据重复性很大,极个别需要修改的属性。
*对象初始化过程比较复杂。
*在运行时刻不方便获取原型的类时,也可以通过原型模式来实现。
20.Prototype模式的要点:
*用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,且拥有稳定的接口。
*使用步骤:首先注册一个新类的对象(即原型),最后在需要的地方调用定义的克隆方法。
*Prototype模式中的克隆方法可以利用.NET中的Object类的MemberwiseClone()方法或者序列化来实现深拷贝。
2.设计模式之禅+大话设计模式 之建造者模式
1.重构的目的(了解):
简单、清晰
2.什么是建造者模式呢?
建造者模式又称生成器模式,是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
3.建造者的通用类图是什么样子呢?
4.建造者模式的通用代码:
*产品类:通常是一个组合或继承(如模板方法模式)产生的类。
——如果有多个产品类就有几个具体的建造者,并且这多个
*导演类:具有封装的作用,使高层模块与建造者内部的实现类相分离。当建造者模式庞大时,可以有多个导演类。
5.建造者模式的优点:
*封装性:客户端不知道产品内部的实现细节
*建造者独立,容易扩展
*便于控制细节风险:因为具体的建造者是独立的,所以对建造过程逐步细化时,不影响其他的模块。
6.建造者模式的使用场景:
7.建造者模式与工厂模式的区别:
建造者模式关注的是调用方法的顺序,基本方法已经实现。
工厂模式关注的是创建零件。
8.切记:别孤立思考一个模式,可以在使用建造者模式时考虑下模板方法模式。
3.UML之状态机视图+活动视图+交互视图
1.概述状态机视图的作用:
用于对对象的生命周期进行建模,显示对象如何根据当前状态对不同事件做出反应的动态行为。 状态机图主要由状态和转换两种元素组成。
2.状态机:
*定义:是由状态和迁移组成的图。
*组成:状态机主要由状态、转换、事件、动作和活动5部分组成。
1)状态表示对象的生命周期中的一种条件或情况。
2)转换表示两种状态间的一种关系。
3)事件表示在某一时间与空间下所发生的有意义的事情。
4)动作表示一个可执行的原子操作,是UML能够表达的最小计算单元
5)活动表示状态机中的非原子执行,一般由一系列动作组成。
*作用:状态机图用于对系统的动态方面进行建模,适合描述一个对象在其生命周期中的各种状态及状态的转换。
*优点:帮助理解控制机制。
*应用环境有两种:
->(一般情况下)应用到类上,就描述类实例对接收事件的响应。
->应用到操作、用例、协作上,就描述它们的执行过程。
*工作步骤:从对象的初始状态开始,响应时间并执行相应动作,从而完成状态的转换;在新状态下又继续响应事件并执行动作,如此循环进行到对象的终结状态。
3.事件:
*定义:是具有时间和空间位置的显著发生的某件事。发生在时间点上,不具有持续时间。
*作用:表达了对象可以检测的变动——对象间的调用或显式信号、某个值的改变或时间的推移。
*种类:调用事件、变更事件、信号事件、时间事件
->调用事件:表示对象接收到一个调用操作的请求。其期待的结果是事件的接收者触发一个转换并执行相应的操作。
->变更事件:变更事件的发生依赖于事件中某个表达式的布尔条件。变更事件没参数,只有条件被满足才会触发变更事件。 只有当更显式通讯形式不合适时使用。 当变更事件持续的被求值直到为真,此时迁移被触发。
->信号事件:发送对象显式的创建和初始化信号实例,并发送给一个或若干个对象。 在类图中使用关键字《signal》作为分类来声明,信号参数声明为属性,可以使用概括关系,信号也可以是其他信号的孩子。
->时间事件:时间事件的发生依赖于事件中的一个时间表达式。比如:可以让对象进入某一状态后经过给定的时间(相对时间)或到达某个绝对时间(某天某时刻)后发生该事件。
4.状态:
*作用:描述了对象生命周期的一段时间。状态机中,一系列状态由迁移来连接。状态用带圆角的长方形表示
*状态分两种情况:
——相同状态对相同的事件作出相同的响应。
——不同状态对相同的事件作出不同的响应。
也就是说:状态不同,对相同事件的响应就不同。
*复合状态:复合状态可以分解为连续的或并发的子状态。
-> a.顺序复合状态:当顺序复合状态被激活时,只有一个子状态会被激活。
->b.并发复合状态:复合状态中包括两个或多个并发执行的子状态机。
*简单状态:简单状态无子结构,只有若干迁移和可能的进入和退出动作。
*种类:
5.转换:
*定义:转换是两种状态间的一种关系,指明当特定事件发生或特定条件满足时,处于某状态(源状态)的对象将执行某一动作或活动并进入另一状态(目标状态)。
*表示:转换表示为从源状态指向目标状态的实线箭头,并附有转换的标签。
*种类:转换与隐式动作的种类:
6.动作:
*迁移被激发时,它的动作(如果存在)被执行。系统可以同时执行多个动作。动作一旦开始,它必须结束且不能为其他同时间的动作所影响。
*种类:
7.活动视图:
*定义:是状态机的一种对计算和工作流建模的特殊形式。
8. 活动图:
*定义:是UML对于系统的动态行为建模的另一种常用工具,它描述活动的顺序,展现从一个和活动到另一个活动的控制流。
*组成:活动图的组成元素:
-1、活动状态图(Activity):用于表达状态机中的非原子的运行。
-2、动作状态(Actions):是指原子的,不可中断的动作,并在此动作完成后通过完成转换转向另一个状态。
-3、动作状态约束(Action Constraints):用来约束动作状态。
-4、动作流(Control Flow):表示动作之间的转换,用带箭头的直线表示,箭头指向转入的方向。
-5、开始节点(Initial Node):用实心黑色圆点表示。
-6、终止节点(Final Node):分为活动终止结点(表示整个活动的结束)和流程终止结点(表示子流程的结束)。
-7、对象(Objects)
-8、数据存储对象(DataStore):使用关键字《database》表示。
-9、对象流(Object Flows):是动作状态或活动状态与对象之间的依赖关系。对象流用带有箭头的虚线表示。如果箭头是从动作状态指向对象,则表示动作对对象施加了一定的影响。施加的影响包括创建、修改和撤销等。如果箭头从对象指向动作状态,则表示该动作使用对象流所指向的对象。
-10、分支与合并(Decision and Merge Nodes):用菱形表示。
-11、分叉与汇合(Fork and Join Nodes):分为水平方向和垂直方向。
-12、异常处理(Exception Handler):当受保护的活动发生异常时,出发异常处理节点。
-13、活动中断区域(Interruptible Activity Region):活动中断区域围绕一些可被中断的动作状态图。
-14、泳道(Partition):
泳道将活动图中的活动划分为若干组,并把每一组指定给负责这组活动的业务组织,即对象。在活动图中,泳道区分了负责活动的对象,它明确地表示了哪些活动是由哪些对象进行的。在包含泳道的活动图中,每个活动只能明确地属于一个泳道。
泳道是用垂直实线绘出,垂直线分隔的区域就是泳道。在泳道的上方可以给出泳道的名字或对象的名字,该对象负责泳道内的全部活动。泳道没有顺序,不同泳道中的活动既可以顺序进行也可以并发进行,动作流和对象流允许穿越分隔线。
9.交互视图:
*作用:提供了描述一系列对象行为更全局的视图。
*表示:使用协作来建模。
*种类: 交互图类型:分为顺序图和协作图
——顺序图:
*定义:以互相作用的一组对象为中心进行考察的图。
*适用范围:体现对象间消息传递的时间顺序。
*组成:
->参与者或对象:是系统的参与者或者任何有效的系统对象。主要参与者放在最左边,从左向右排列。
->生命线:每个对象都有生命线,是一条垂直的虚线,用来表示对象在一段时间内是存在的。如果对象生命周期结束,则用注销符表示。
激活/控制焦点:表示对象执行一个动作的时间。用生命线上长条矩形表示,高度描述了激活持续的时间。
-> 消息:用带箭头的实线表示。
消息的种类:
调用(同步消息):表示调用某个对象的一个操作。
返回(同步返回):表示被调用对象向调用者返回一个值。
发送(异步消息):向一个对象发送一个信号,实例间通信的异步激发机制。
创建和销毁
->交互片段
——协作图
*定义:以独立的对象为中心进行考察的图。
*适用范围:显示过程设计细节。
*组成: 协作图的元素:
对象:一个协作代表了为了完成某个目标而共同工作的 一组对象。
消息:描述了系统的动态行为。
链:说明一个对象是如何与另一个对象进行连接的。