定义:
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、
让代码更容易被他人理解、保证代码可靠性。
举例 :比如说我们在下象棋,其中下象棋的过程中有多种可以一招将对方将死的旗招,比如说:双炮,错马,错车 等 。我们将这些可以一招将对、
方至于死地的招数总结为一套模式,只要我们将自己的棋招接近这套模式,按着这套模式思维来下棋,就可以赢下对方。这就是设计模式所给我们.
带来的好处。如果说框架的使用为武侠小说里的六脉神剑那话,那么好的设计模式的架构 就是金刚不坏之身。
guf(4人帮):设计模式23种:
Factory(工厂模式), Builder(建造模式), Factory Method(工厂方法模式),
Prototype(原始模型模式),Singleton(单例模式), Facade(门面模式),
Adapter(适配器模式), Bridge(桥梁模式), Composite(合成模式),
Decorator(装饰模式), Flyweight(享元模式), Proxy(代理模式),
Command(命令模式), Interpreter(解释器模式), Visitor(访问者模式),
Iterator(迭代子模式), Mediator(调停者模式), Memento(备忘录模式),
Observer(观察者模式), State(状态模式), Strategy(策略模式),
Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)
分类: 按设计模式的分类 主要分为 3大 类 :1:对象创建型 2: 对象结构型 3:对象行为型
A: 对象创建型
1:单例模式:在jvm里确保了一个类只有一个实例存在
如生活中:当消费者用刷卡的形式来付款的时候 每次客户付款 超市的流水帐号都是不同的.....
如果说这个例子不经典还有:地球只有一个太阳:等等这就是单例模式的所在:单例模式它具有 以下特征:
1:有一个private 修饰 类名级别的静态属性:
2:构造方法必须是一个Private 修饰的构造方法,防止其他的类调用该类的构造方法:
3:提供的方法是由public修饰,静态的,同步的的方法做为改类的访问点:
代码示例:懒汉式
public class Person(){
private static Person person = null;
private Person(){}
public static synchronized getPerson(){
if(person =null){
return new person();
}else{ return person;}
}
}
代码示例:饿汉式 饿汉式是非常的饿,在类装载的时候就初始化这个对象了
public Class Person(){
private static Person person =new Person();//类加载就会初始化
private Person(){}
public Person getPerson(){
return person;
}
}
项目中的应用:用的最多的,也就是数据库连接池类,这个类设置为单例类,保证那次调用的都是同一个connection对象。
2:简单工厂模式:
就是在传统的mvc架构里,在控制层,通过工厂类来代替new关键字生成对象来实行一系列的操作:就是代替了用new关键字生成对象的误区...解决了类与
类之间的直接依赖关系....
2:抽象工厂模式:
定义 : 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
抽象工厂模式是一种比工厂模式抽象程度更高的模式。简而言之,抽象工厂类和工厂类的原理相同,只不过工厂类返回的是普通类的实例;而抽象工厂类返回的是一个工厂类的实例。
在我们项目的最主要的使用主要是换换皮肤技术
3:建造模式(Builder):
建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。
建造模式使得产品内部表象可以独立的变化, 客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
目的 :其意图是将一个复杂对象的构建与他的表示分离,使得同样的构建创建过程可以创建不同的表示。
适用性:
- 当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时
- 当构造过程必须允许被构造的对象有不同的表示时。
2:对象结构型 :
1:组合模式:
定义: 将对象以树型结构的形式组合起来,以达成部分与整体的层次结构,使客户端不管使用单个对象,还是组合对象都保持一致性。
解决的问题: 组合模式主要解决了树形数据结构的方案
生活中的例子:公司的成员结构图也就是以树形结构的形式架构起来的,如果公司发加奖金了,只要把最顶层的那个发放金额即可,这就体现了
客户端不管使用单个对象,还是组合对象都保持一致性。
项目中的应用:在删除数据库关联表的时候,首先要删从表,再删主表
2:代理模式
定义:为其它对象提供一种代理,以提供对这个对象的访问 说白了也就是 这个对象不想或者不能直接引用那个对象 它会让代理对象来引用那个对象,而代理
对象在源对象,与目标对象之间起到了中介的作用。
好处:降低了调用对象与被调用对象之间的耦合度
生活中的例子:比如说马上要过年了,但是自己还在加班,没有时间去买票,这时我会打电话到票务中心帮忙定一张票,这当然要付出额外的劳务费
当然票务中心不卖票,只有火车站卖票,票务中心卖给你的票是通过火车站来实现的.....从这个例子可以看出,我就是源对象,买票是目标对象 票务中心
为代理对象,火车站为真实对象
项目中的应用:spring Aop 中的底层实现用到了代理模式
3:门面模式
定义:为子系统的一组接口提供了一个高层接口,做为该系统的访问点
外部对象通过统一的门面对象与子系统交互
门面模式为子系统的一组接口提供了一个统一的高层接口来供外部对象调用,做为该子系统的访问点 使这个子系统更加容易使用
解决的问题:子接口繁多,调用复杂 内部交互的地方比较多
生活中的例子:消费者拨打一个电话与客户代表联系,这个客户代表就是 扮演了这个 ‘外观’ 它包括了 订货部 收银部,送货部 的接口,消费者只要跟高层接口客户代表联系就可了
项目中的应用:比如说,jdbc操作数据库的时候,每次都要加载驱动,通过driverManager类得到连接对象,再通过连接对象得到statmem对象,
statmen对象执行sql语句..返回resultSet对象结果集, 对这个resultSet结果集进行遍历,再关闭数据库连接
这一系列的过程的非常的繁琐,我们将不变的部分 提炼出来做成一个接口..这就引用了外观对象,当我们的数据库由mysql变成oracle的时候,我们只要在
那个接口里改一下驱动即可.....
4:适配器模式
定义:将一个类的接口转换为客户类希望的另外一个接口 使原本接口不谦容,不能工作在一起的类,能在一起工作
解决的问题:已经存在类似功能的类和接口,但方法签名不一样
生活中的例子:美国的生活电压 是 110 v 而中国的生活电压 是220v 如果要在中国使用美国电压也就要通过电压器来转换。
项目中的应用:
5:装饰器模式
定义:动态的给一个对象添加额外的功能
解决的问题:一个对象要经常动态添加属性和职责
生活中的例子:比如说我要对我家的房子装修,首先刮上998 ,然后 美化天花板 ,再给墙必上添上巨幅海报 来达到美化的效果。
项目中的应用:
3:对象行为型:
1:命令模式
定义:将来自客户端传入的对象,我们无需了解这个请求激活的动作,以及处理请求的细节
解决的问题:只关注对象的行为,不关心具体实现
举例说明:神话小说里,玉皇大帝要招美猴王上天,他会拟一道圣旨派遣太白金星下凡去宣告这份圣旨,而玉皇大帝就是客户端,太白金星就
是命令的发送者,圣旨就是命令,而美猴王就是命令的接受者......玉帝的这一道命令就是要求猴王到上界报到。
玉帝只管发出命令,而不管命令是怎样传达到美猴王的。太白金星负责将圣旨传到,可是美猴王怎么执行圣旨、何时执行圣旨是美猴王自己的事。
项目中的应用:项目中我们要录制一段宏,这段宏可以记录用户的操作,当出现错误操作的时候,以便于用户进行撤销操作,当我们运行这段宏的时候,它会把用户
的操作记录播放一次,我们只管录制这段宏,以及播放这段宏,不管他是怎么去具体执行的。
2:模版模式
定义:父类定义流程,子类去实现这个流程。
解决的问题:解决了代码和流程的重复问题。
如果说软件开发中最常用的模式是那个的话,那么就属模版模式了
项目中用的应用:spring里面的模版类,以及jdbcTeamlate
3: 策略模式
定义:定义了一系列的算法,把他们一个个封装起来,使他们可以相互的替换。但是达到的目的是一样的
解决的问题:相同问题的不同种解决方案。
生活中的例子:我们到超市购物,我们可以选择使用现金付款,也可以选择使用刷卡的方式。
我们保存图片的时候,可以有多种保存的形式,如 jgp gif 等。
项目中的应用:我们在把数据库中的数据,导出来的时候,我们可以把数据置入exec文件中保存,也可以置入xml文件中保存数据。
4:观察者模式
定义:定义了对象之间一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象都会得到通知以及自动更新
解决的问题:解决了多个对象之间的相互依赖关系的相互通知。
生活中的例子:在交通方面,当为红灯的时候,所以的车子会停止前进,当灯的状态发生改变的时候,由红灯变为绿灯的时候,车子就往前前进
项目中的例子:就是mvc架构的系统,model层对应多个试图层,当model层的数据发生改变的时候,试图层的数据也会自动的改变,显示给用户看。
5:状态模式
定义:不同的状态,不同的行为。
状态模式 通过内部对象的改变来控制自己的行为,这样大量解决了if else if 的用量,我们不用通过if else if 来判断此对象的状态,状态模式会根据
状态的改变来提供不同的处理方式来实现我们想要的操作。
生活中的例子:我们的银行卡,如果我们在输入密码的时候,输入3次都没有正确的话,系统会将
我们的卡保持为锁定状态,此时此刻我们不能进行一系列的银行业务为操作,只能让银行服务人员为我们的卡解锁:解锁之后
我们的卡就保持着一种正常状态,就可以实现一系列的银行操作业务。
项目中的应用:在权限方面的应用:如果判定某个用户的状态为全方为的状态的话,就可以对系统
进行所有的操作,然而判定此用户为局限状态的话,就可以对系统的部分功能进行操作。
6:职责链模式
定义:为了避免请求发送者和接受者之间的耦合关系 ,使多个接受对象都有机会处理,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止
解决的问题:有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
你想在不明确指定接受者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应该被动态的指定。
生活中的例子:比如说,在篮球比赛中,一号 传给 7号,7号传给 3号,3号传给 8 号,最后由8号完成得分。这样的流程就是一条链的模式。
项目中的应用:struts1源码中的执行就用到了职责链模式。
7:中介者模式
定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
解决的问题:一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
一个对象引用其他很多对象并且直接与这些对象通信,导致难以服用该对象。
想定制一个分布在多个类中的行为,而又不想生成太多的子类。
描述:就一个类而言,应该仅有一个引起它变化的原因。
描述:"对于扩展是开放的"(Open for extension)。这意味着模块的行为是可以扩展的。当应用的需求改变时,可以对模块进行扩展,使其具
描述:若对每个类型S的对象O1,都存在一个类型T的对象O2,使得在所有针对T编写的程序P中,用O1替换O2后,程序P行为功能不变,则S是T的子类型。
应用:在实现继承时,子类型(subtype)必须能替换掉它们的基类型(base type)。如果一个软件实体使用的是基类的话那么也一定适用于子类。但反过来的代换不成立。
个 人观点: LSP是使OCP成为可能的主要原则之一,对LSP的违反将导致对OCP的违反,同时二者是OOD中抽象和多态的理论基础,在OOPL中表现为继承。在高 级语言(JAVA、C#)中,只要我们严格按照接口和虚拟类的语法规范来做就能很好遵循此原则,另外我们还应该避免一些更微妙的违规情况。举个例子,正方 形和矩形,矩形可以做为正方形的基类,因为正方形也是一种矩形,但对于正方形来说,setWidth()和setHeight()是冗余的,且容易引起错 误,这样的设计就违反了LSP原则。如果有两个具体类A和B之间的关系违反了LSP,可以在以下两种重构方案中选择一种:1 .创建一个新的抽象类C,作为两个具体类的超类,将A和B共同的行为移动到C中,从而解决A和B行为不完全一致的问题。 2 .从B到A的继承关系改写为委派关系。
6:接口隔离原则(ISP)
描述:不要强迫客户依赖于它们不用的方法。
应用:一个类对另外一个类的依赖性应当是建立在最小的接口上的。如果客户端只需要某一些方法的话,那么就应当向客户端提供这些需要的方法,而不要提供不需要的方法。提供接口意味着向客户端作出承诺,过多的承诺会给系统的维护造成不必要的负担。
结论:使用多个专门的接口比使用单一的接口要好。
遵循以上原则,可以使我们的软件更具灵活性,强壮性。但灵活是需要付出代价的,由多态带来的性能损失就是最明显的一个问题。所以我们需要权衡,需要做出选择,在灵活与性能之间做出选择。
迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。英文简写为:
LoD. 迪米特法则
狭义的迪米特法则的缺点:
在系统里造出大量的小方法,这些方法仅仅是传递间接的调用,与系统的商务逻辑无关。
遵循类之间的迪米特法则会是一个系统的局部设计简化,因为每一个局部都不会和远距离的对象有直接的关联。但是,这也会造成系统的不同模块之间的通信效率降低,也会使系统的不同模块之间不容易协调。
门面模式和调停者模式实际上就是迪米特法则的应用。
广义的迪米特法则在类的设计上的体现:
优先考虑将一个类设置成不变类。
尽量降低一个类的访问权限。
谨慎使用Serializable。
尽量降低成员的访问权限。