UML
状态机视图
1.概述
状态机视图是通过对类的对象的生存周期建立模型来描述对象随着时间变化的动态行为。每一个对象都被看做通过事件进行探测反应来与外界其他部分进行交互的独立实体。事件是对象可以追踪到的,存在一系列运动状态的变化。状态就是对象的一组描述事件的属性值。状态机就是对象在对事件反应属性值描述和特定的行为。下面是我想到的一个例子:一台微波炉,具有关机状态,加热状态,保温状态等等。微波炉的每一个状态都有一些特定的行为,例如关机状态可以开机进入加热或者保温状态。
2.状态机
状态机是展示状态与状态转换的图。通常一个状态机依附于一个类,描述一个类的实例对接收到事物做出的反应。状态机也可以依附于操作,用例和协作并描述它们的执行过程。状态机是一个类的对象所有可能的生命历程模型。状态机是一个对象的局部视图,一个将对象与其外部世界分离并独立考察其行为的图。
3.事件
事件就是在时间和空间上发生的值得注意的事情,它是瞬时的。如果某一事情对状态机造成了影响,那么在状态机模型中它是一个事件。当我们使用事件这一个词的时候,通常是指一个事件的描述符号,即对所有具有相同型式的独立发生事件的描述。一个事件的具体发生叫做事件的实例。对类而言,信号利用泛化关系进行组织,以使不同的类共享公共的结构。事件可以明确的或者隐含的分为:信号事件、调用事件、改变事件、时间事件等等。
信号事件。信号事件通过发送信号来改变状态机的状态。
调用事件是一个对象对调用的接受,这个对象用状态转化转换完成操作。
改变事件。当是依赖于特定属性值的布尔表达式所表示的条件满足时,事件发生改变。
时间事件。是指随着时间的变化导致状态的转换。例如session的时间设置,超期自动切换为非登录状态。
4.状态
状态描述了一个类对象的生命周期中的一个时间段。它可以用三种附加方式说明:在某些方面性质相似的一组对象值,一个对象等待一些事情发生时的一段时间,对象执行持续活动时的一段时间。在状态机中,一组状态由转换相连,虽然转换连着两个状态,但是状态转换只能由转换出发的状态处理。
活动视图
活动视图是状态机的一种对计算和工作流建模的特殊形式。 活动图的状态代表了运算执行的状态,而非一般对象的状态。 通常活动图假设无外界的基于事件的 中断来影响计算过程。
活动图是活动视图的标记形式。它包含了 一些方便使用的速记符号,事实上,这些符号可以用于任何的状态图中, 尽管混合的标记有时可能会很难看。
泳道 根据责任来在模型中组织活动常常是非常有用的。例如,将由某个商业组织控制的活动划分在一起,这类划分可以通过图中分隔的区域来表达。由于它们的外观,每个区域被称为泳道。
对象流 活动图不但可以显示控制流,还可以显示对象取值的流。对象流的状态表达了对象是活动的输入还是输出。对于输入值,由对象流状态至活动的虚线来表示。如果活动具有一个以上的输出值或后续的控制流,则箭头从分叉的符号出发。类似的,多个输入值则汇集至连接符号。
交互视图
· 交互视图
交互视图描述了执行系统功能的各个角色之间相互传递消息的顺序关系。类元是对在系统内交互关系中起特定作用的一个对象的描述,这使它区别于同类的其他对象。交互视图显示了跨越多个对象的系统控制流程。交互视图可用两种图来表示:顺序图和协作图,它们各有不同的侧重点。
· 顺序图
顺序图表示了对象之间传送消息的时间顺序。每一个类元角色用一条生命线来表示—即用垂直线代表整个交互过程中对象的生命期。生命线之间的箭头连线代表消息。顺序图可以用来进行一个场景说明—即一个事务的历史过程。
顺序图的一个用途是用来表示用例中的行为顺序。当执行一个用例行为时,顺序图中的每条消息对应了一个类操作或状态机中引起转换的触发事件。
· 协作图
协作图对在一次交互中有意义的对象和对象间的链建模。对象和关系只有在交互的才有意义。类元角色描述了一个对象,关联角色描述了协作关系中的一个链。协作图用几何排列来表示交互作用中的各角色。附在类元角色上的箭头代表消息。消息的发生顺序用消息箭头处的编号来说明。
协作图的一个用途是表示一个类操作的实现。协作图可以说明类操作中用到的参数和局部变量以及操作中的永久链。当实现一个行为时,消息编号对应了程序中嵌套调用结构和信号传递过程。
顺序图和协作图都可以表示各对象间的交互关系,但它们的侧重点不同。顺序图用消息的几何排列关系来表达消息的时间顺序,各角色之间的相关关系是隐含的。协作图用各个角色的几何排列图形来表示角色之间的关系,并用消息来说明这些关系。在实际中可以根据需要选用这两种图。
创建型模式
创建型模式简单来说就是用来创建对象的。一共有五种:单例模式、建造者模式、工厂方法模式、抽象工厂模式、原型模式。
单例模式
定义:确保某一个类只有一个实例,并且提供一个全局访问点。
主要实现步骤:
- 将该类的构造方法定义为私有方法,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例;
- 在该类内提供一个静态方法,当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用。
适用场景:
1.需要生成唯一序列的环境
2.需要频繁实例化然后销毁的对象。
3.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
4.方便资源相互通信的环境
优点:
1, 在内存中只有一个对象,节省内存空间;
2, 避免频繁的创建销毁对象,可以提高性能;
3, 避免对共享资源的多重占用,简化访问;
4, 为整个系统提供一个全局访问点。
缺点:
1, 不适用于变化频繁的对象;
2, 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
3, 如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失;
注意:
- 尽量减少同步块的作用域;
- 尽量使用细粒度的锁。
建造者模式
定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。
优点:
- 封装性好,构建和表示分离。
- 扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
- 客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
缺点:
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
模式的结构
- 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
应用场景:
- 相同的方法,不同的执行顺序,产生不同的结果。
- 多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
- 产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
- 初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
工厂方法模式 :
定义:让子类来决定要创建哪个对象。
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
缺点:
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
- 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
应用场景:
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌
1. 模式的结构
工厂方法模式的主要角色如下。
- 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
- 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
建造者模式和工厂方法模式的区别
- 建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
- 创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
- 关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成。
- 建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样。
抽象工厂模式:
定义:
提供一个创建一系列相关或者相互依赖对象的接口,而无需知道他们的具体类,抽象工厂模式也称Kit模式,它属于类创建型模式。
优点
- 抽象工厂模式隔离了具体类的生成, 使得客户并不需要知道什么被创建。 由于这种隔离,更换一个具体工厂就变得相对容易, 所有的具体工厂都实现了抽象工厂中定义的那些公共接口, 因此只需改变具体工厂的实例, 就可以在某种程度上改变整个软件系统的行为。
- 当一个族中的多个对象被设计成一起工作时, 它能够保证客户端始终只使用同一个族中的对象。
- 增加新的族很方便, 无须修改已有系统, 符合“开闭原则”。
缺点
- 增加新的等级结构麻烦, 需要对原有系统进行较大的修改, 甚至需要修改抽象层代码,这显然会带来较大的不便, 违背了“开闭原则”。
使用场景
- 一个系统不应当依赖于具体类实例如何被创建、 组合和表达的细节, 这对于所有类型的工厂模式都是很重要的, 用户无须关心对象的创建过程, 将对象的创建和使用解耦;
- 系统中有多于一个的族, 而每次只使用其中某一族。 可以通过配置文件等方式来使得用户可以动态改变族, 也可以很方便地增加新的族。
- 属于同一个族的对象将在一起使用, 这一约束必须在系统的设计中体现出来。 同一个族中的对象可以是没有任何关系的对象, 但是它们都具有一些共同的约束, 如同一操作系统下的按钮和文本框, 按钮与文本框之间没有直接关系, 但它们都是属于某一操作系统的, 此时具有一个共同的约束条件: 操作系统的类型。
- 等级结构稳定, 设计完成之后, 不会向系统中增加新的等级结构或者删除已有的等级结构。
原型模式:
定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
何时使用:
1、当一个系统应该独立于它的产品创建,构成和表示时。
2、当要实例化的类是在运行时刻指定时,例如,通过动态装载。
3、为了避免创建一个与产品类层次平行的工厂类层次时。
4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
优点:
1、性能提高。
2、逃避构造函数的约束。
缺点:
1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
2、必须实现 Cloneable 接口。
使用场景:
1、资源优化场景。
2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
3、性能和安全要求的场景。
4、通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
5、一个对象多个修改者的场景。
6、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
注意事项:与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。
浙公网安备 33010602011771号