前言
1.见得比较少,对设计模式可以使用的地方,还不是很清楚,我想这是一条充满惊喜的路。
2.了解了设计模式的内容,有了一定的理解,和之前学习最大的不同之处就是面向对象的设计方法,使得我们设计的软件更加具有灵活性,可维护性好,复用性强。
3.更加清楚的认识到现在的学习真的才刚刚开始,自己要好好珍惜现在的学习时光。
总体认识
学习了设计模式之后,发现我们一定要紧紧围绕着设计模式的基本原则来设计,对于各个模式的理解,大致可以分为三大类:建造者模式,行为型模式,结构型模式。我感受到的是设计模式使得对象和类之间的耦合度降低,充分提高代码的扩展性和复用性。以下是一个总体的认识:
设计原则
1单一职责
一个类有一个职责,如果一个类的职责过多的话,等于把这些职责耦合在一起,一个职责的变化可能会影响到这个类其他职责的完成情况。
2开放-封闭
对扩展开放,对修改关闭。这是面向对象设计的核心,遵循这个原则可以使软件开发可维护,可扩展,可复用,灵活性大。我认为修改会导致在没有完全了解软件结构的情况下,会错上加错,当然,也没有绝对的封闭,这时就需要做适当的预判了吧。
3里氏代换
子类型必须完全替换父类型。为什么这么说呢?子类型继承父类,在用到父类的地方,必须能够完全代表父类的角色去使用,这样才可以做到在不需要修改的前提下进行扩展。
4依赖倒转
1.高层模块不依赖于低层模块,两个都依赖于抽象。2.抽象不该依赖于细节,细节依赖于抽象。
面向对象的优点是可维护,可复用,可扩展灵活性好。那么我认为最关键的就是抽象了,这一步提高了,对于代码的复用我们可以很好的做到吧。
5迪米特法则
最少知识法则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的交互作用,这时可以通过第三方参与完成一个类调用另一个类的操作。
6合成/聚合复用
当我们用到关系的时候,常常想的就是继承,当然这也是一种办法,不过继承就意味着关系很紧密,父类一旦变化,子类就会跟着变化,这时我们要用到合成/聚合关系。合成:整体部分的关系,部分离开整体没有存在的意义了。聚合:当部分离开整体仍然有独立存在的意义。
设计模式
一 建造者模式
1简单工厂
相当于一个模子,根据已经可以正常实现功能的原样(已经封装好的一个可以独立工作的类),刻出新的样品来。这个工厂是如何实现的呢?通过工厂中的一些特定参数,来指定工厂生产。特点:
1.专门抽象出一个类只进行实例化,耦合度降低了。2.违背了开放封闭的原则:因为我们如果想要增加一种产品的话,需要增加一个类,同时还要在工厂中进行修改,添加一个参数。
如下是UML图,(声明:以下所有的图是根据自己的理解,对教材中的原图进行相应的改动或简化,如有不足请多指点。)
2工厂方法
工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。工厂方法VS简单工厂
工厂方法是简单工厂的解耦和,怎么说呢,简单工厂里根据参数来确定要new的类,工厂的方法,直接把参数要确定的内容给独立开来了,成为工厂方法的子类,有时候直接调用(跟简单工厂的方法类似)这样实现优化简单的工厂的开关原则。3抽象工厂
抽象工厂,在工厂方法的基础上,再抽象出来一个可以称之为父类的更加抽象的工厂,同时可以new的类也不是单单具体的类了,这些具体的类还可以再抽象。特点:
1.充分体现了依赖倒转原则,和开闭原则。2.增加新产品的时候会有在多处有变动,同时需要在具体工厂做添加工作。
3.可以用到反射。
以下是uml图,画的很简单:
缺点:
增加一个产品时,需要在工厂方面:增加抽象工厂的方法,具体工厂的方法,在抽象类方面:增加该产品操作的抽象类,增加具体类。
4建造者
当我们构建一个东西时,他的内部结构很复杂,我们用建造者模式来做,将构建所需的方法全部封装在一个抽象类,我们再去继承这个类,这样不会使我们面对复杂的过程少一些步骤。建造者模式是将内部复杂的建造过程和表现分离,这时就需要一个指挥者,你需要造什么,就跟建造者说,这样达到了更好的分离。
以下是uml图:
5原型模式
用原型克隆出新的东西,其实对原型的一个实例化。这里原型可以是一个抽象的类,可以创建新的东西的方式就喜欢将其实例化。说明:
.Net的库中对于克隆,写好了一个接口ICloneable,可以直接用。调用的方法是:MemberwiseClone()以下是uml图:
6单例
一个类只有一个实例,并提供一个访问它的全局访问点。特点:
一个类只有一个功能,使得我们对这个功能修改时,需要参与的修改的类比较少。
二 结构型模式
7装饰模式
动态的给一个对象添加一些额外的职责,从增加功能的角度来看,比生成子类更为灵活优点:
把类中的装饰功能从该类中搬移出去,这样可以简化原有的类。
8代理模式
代表别的对象去执行操作,我认为这样做的目的可以为原来的对象减负。这里真正的操作,是代理者在操作。以图说明:
9外观模式
外观模式,对一组系统,提供统一的管理界面,这样我们需要访问某一系统的时候,只要访问这个界面,就可以达到我们的目标。优点:
1.方便对子系统的统一调用,为访问提供一个简单的接口。2.减少子系统之间的耦合。
10适配器模式
将一个类的接口转换成用户所需要的接口,这时用到适配器,来做转换工作,解决接口的不兼容性。11组合模式
用户对单个对象和组合对象的使用具有一致性,在我们遇到整体和部分层次问题是,可以使用。我们可以用一个接口或者抽象类,让整体和部分都去实现接口,这样他们的功能在外部看来就是一致的了。效果:
想让整体和部分一致对待,或者说单个对象和组合对象一致对待。用户不用考虑内部。12桥接模式
将抽象部分与它的实现部分分离,使他们都可以独立的变化。 避免了继承的高耦合性。既然是桥接,就有桥的意思,那他们之间是如何联系的呢,联系方式是一种原则,组合/聚合原则。
优点:
很多时候我们可以用子类去继承父类,从而去使用父类的东西,或是去实现一个接口,这种继承的关系是一种强耦合的关系,一旦父类变化,子类就需要跟着变化。桥接模式正好进行了一个解耦和的作用。13 享元模式
有一个享元超类,泛化出具体的子类,这时有一个享元工厂,使得享元类更好的被共享,当用户需要使用这个享元类实例的时候,工厂可以自动返回一个已有的实例,或者创建一个没有(如果不存在的话)。目的:
减少存储空间。对于没有的只实例化一次,对于已有的对象不用再实例,只是索引的不同(我认为)
三 行为型模式
14策略模式
策略模式,对不同的算法进行了封装,具体的算法之间耦合度降低,同时可以相互替换。而这个相互替换,就是下图中context的作用,它的存在可以调用具体的算法。15模板方法
定义一组操作的基本框架,将他的一些步骤延迟到子类中qu 实现。这个基本框架我们可以理解为一个模板,子类可以使用这个模板,并可以增加一些自己的独特性。除了更详细的实现层次上不同外,其他的过程或步骤是一致的,我们可以用模板方法来处理。
优点:
把不变行为搬移到超类,去除子类中的重复代码来实现它的优势。16观察者模式
定义了一种一对多的对应关系,多个观察者可以同时监听一个对象,当这个对象发生变化时,会通知观察者,观察者会做出具体的反应。条件:
什么时候需要使用观察者模式呢,当一个对象状态的改变会影响到其他对象的改变时,就需要用到观察者模式,观察者是抽象依赖抽象,我们不需要具体的对象相互作用。观察者模式是一个解耦合的过程,我们做的是让抽象依赖于抽象。不足:
对于一个接口中的方法,对不同的对象,我们不能让他们直接实现这个方法,那么我们就要间接的去实现,那么如何实现呢?事件委托
委托事件可以把方法装上,装上了之后就与该方法具有完全相同的行为。委托方法的使用,可以像其他任何方法一样可以有参数和返回值。一个委托可以装上多种方法。
注意
委托事件所搭载的方法,必须具有相同的原形和形式,也就是要有相同的参数和返回值类型。
17状态模式
状态模式,当对象的状态发生改变时,他的行为会做出相应的变化。同时还有一个context联系上下文,将跟状态有关的东西放在一起,维护具体的状态类。同时状态需要改变时,可以转换。
优缺点:
1.将同一状态的行为封装在一起,很容易进行扩展。同时各个状态之间的耦合度相应降低。2.不同的状态在转换的时候,还是有些交互。我认为应该可以优化的。
18备忘录模式
我们可以回到上一个时刻的状态的一种模式,对于这种情况的实现,我们可以有一个存储箱,将自己现在的状态存在里面,随着时间的流逝,自己(发起人)想要穿越了可以把存储箱的东西给了现在的自己,那就变成了过去的那个状态,这时需要提一点的是有一个管理员来保管存储箱,为啥这么做呢,便于封装,我们获得前一个时期的状态,只要与管理员联系就可以了,而不必对存储箱的结构了解。19命令模式
当我们有请求的时候,可以通过执行者完成这个请求,如果直接让执行者执行这个请求,那么类之间的耦合度就会加大,用一个命令用来解耦,使得请求和执行者的分离。将请求封装成一个对象,这个请求可以激活一个命令~不同的请求可以对用户形成参数化。
20职责链模式
申请可以让一个或多个对象都有机会进行处理,避免请求的发送者和接收者之间的耦合关系太强,同时也可以让这个请求得到处理。那么如何实现过个对象都可以处理这个请求,我们在对象之间绑上了联系,这样的话,如果该对象处理不了,就把请求抛给他的上级去处理。优缺点:
1.请求可以被处理,而不用考虑链的结构。2.考虑不全面的时候这个请求可能最终都得不到处理。
21中介者模式
将一系列的对象交互,封装在一个中介者中,这样可以避免各个对象之间直接的相互作用,起到一个解耦和。适用:
一组对象他们的定义良好,但是之间的信息交互复杂。优缺点:
1.对象之间的耦合度降低,只是和中介联系,不用对象之间联系。2.中介的责任过于重大和复杂,很容易写错了。
22访问者模式
对于关系稳定的一个或几个对象有不同的操作,我们将对象和该操作分离,可以方便在增加新的操作的时候直接扩充。分析
1.优点:对于操作类(我们容易操作),我们很容易做到扩充。2.缺点:对于对象结构复杂,不稳地的,在增加一个对象的时候,在操作中会增加很多的方法。因此该方法比较适用于结构稳定的结构及相关算法。
结语
遗留问题
1.适配器模式和解释器模式,他们之间的差别不是能够太理解。
2.这些设计模式,自己看着可以理解,但是要说为什么是这样的,这样为啥比较好,对他们的设计初衷,我现在还是体会不到。
3.对于模式中画的uml图,有些线的关系,自己不太清楚,可以在这方面有所加强。
碎碎念
说实话自己码了这么多,最后也是有小小的成就感,这里不得不说的就是自己的时间管理吧,这段时间的毕业设计,自己的项目也延期了,这是自己要反思的地方了。最后想说的是,对于上面的模式的理解和uml图的画法肯定是不够完善的,希望多多指点~