gof设计模式回顾

gof23根据讲师学习笔记回顾:

1.gof:Gang of Four;叫grasp更具有针对性,解决具体的问题;

---------------------总共分为三大类:

---------创建型:(6):Singleton单例、Builder建造者、简单工厂(也算是吧)、FactoryMethod工厂方法、AbstractFactory抽象工厂 、Prototype原型(注意深复制浅复制)

---------结构型:(7)Adapter适配器、Bridge桥接、Composite组合、Decorator装饰、Facade外观、FlyWeight享元、Proxy代理

---------行为型:(11)TemplateMethod模板方法、Command命令、Interpreter解释器、Mediator中介者、Iterator迭代器、ChainofResponsibility职责连、Observer观察者、      Memento备忘录、

State状态、Strattegy策略、Vistor访问者

---------单例:

1.意图:保证一个类仅有一个实例,并提供一个该实例的全局访问点;

2.sealed;禁止继承,私有静态变量,私有构造函数(防止实例化),公共静态属性

3.普通的单例不安全,考虑到线程需要加lock,

4.c#特有属性satic构造函数,只执行一次,可以把创建实例任务交给他来做

5.三层架构中工厂常见有两种选择(单例或是缓存cache)

6.C#终极单例:利用嵌套类的静态构造函数;

7.克隆也就是原型、序列化破坏了单例;

 

---------建造者:

1.动机:一个复杂对象的创建通常有各个部分的子子对象用一定的算法构成,由于需求多的

       的变化,这个复杂对象的各个子部分经常面临剧烈的变化,但是组合在一起的算法却相对稳定。

2.盖房子案例;

3.主要用于分步骤构建一个复杂的对象,分步骤是一个稳定的算法;体现了封装性;

4.建造者解决的是对象部分的变化(子类),而抽象工厂解决的是对象系列的变化(抽象);

 

---------简单工厂:

1.只有一个工厂,只有一个产品(抽象),有多个子类;体现了里氏替换,和封装变化点;

2.用具和工厂之间达成了契约(接口),工厂根据用户不同的要求提供基于这份约定的不同产品。

 

---------工厂方法:

1.某个对象的创建由于需求的变化经常面临剧烈的变化,但却拥有比较稳定的接口

2.他将一个类的创建延迟到了子类;

3.为工厂添加子类,而每个子类负责创建具体的产品。工厂里氏替换,得到具体工厂再得到产品;

4.案例:磨具和玩具;

5.适用性:1.不知道多要创建对象类的时候、希望有他的子类创建、希望通过配置文件来指定;

6.工厂方法解决单个对象需求变化;抽象工厂解决系列对象的需求变化;建造者解决对象部分变化;

7.个人可以理解,三层中抽象工厂,解决数据库的切换,是一个纵向的过程,而工厂方法是一个横向的过程;

 

---------抽象工厂:

1.面临两个维度:产品的种类(三层中的接口的种类),产品系列(三层中的数据库切换种类)

2.抽象工厂提供子工厂供用户基于契约的各种产品;

3.这里注意一下反射技术:

(1)程序集在bin目录下;

//Assembly:程序集的名称(命名空间)

//classNamespace:命名空间+类名;

Assembly.Load(Assembly).CreateInstance(classNamespace)

(2)指定路径下的程序集

//path:程序集所在路径:比如:C:UserswebofficeDataAccessinDebugDataAccess.dll

//name:命名空间+类名;

Assembly.LoadFrom(path).CreateInstance(name)

(3)

//Assembly:程序集的路径

//classNamespace:命名空间+类名;

Assembly.LoadFile(Assembly).CreateInstance(classNamespace)

 

----------原型:

1.意图:使用原型实例来指定创建对象的种类,然后通过拷贝这些原形来创建新的对象。

2.在类的内部实例化自己想外部提供。这样就将自己复制了出来;

3.C#提供了icloneable接口,还有浅复制的base.Memberwiseclone();就不用在clone内部自己实例化自己

  还得降当前属性值一一付给这个新的对象,直接return base.Memberwiseclone();即可;

4.深复制浅复制的区别:实际上是引用类型的copy是对象还是只是地址;解决的话,那么还得让引用类型

  也进行复制,将复制的值给到新对象的变量即可;

 

---------以上创建型完毕

---------适配器

1.个人认为是解决的是接口转换问题;如何将一些现存对象在新的接口环境下还能使用;

 

---------桥接

1.意图:将抽象部分与实现部分分离,是他们都可以独立的变化。

2.比如角色和权限,如果使用继承的话,破坏了封装和不利于扩展,而使用组合思想,将角色和权限各自

  提取自己的抽象,并按照各自的维度变化,只要组合这些变化便可。

3.体现了复用原则;针对接口编程;实现了抽象与实现相分离;

4.使用两个非常强的变化维度;

 

---------组合:

1.具备容器特征的对象,类似自己聚合自己层层嵌套,和容易想起树形控件、和递归调用;

2.为了让一个复杂的对象处理起来就像处理一个简单的对象;

 

 

----------装饰:

1.动机:通过继承来扩展对象的功能,由于继承引入了静态特性,使之缺乏灵活性,但是如果动态

  添加功能则很灵活。

2.两层抽象;

3.实现了动态的扩展功能,可以创建不同行为组合,体现出顺序;

4.缺点,会使用比继承更多的对象,变得错中复杂;

5.它并不是解决多子类衍生的多继承问题,而桥接则解决这个问题,装饰主要解决在多个方向扩展功能;

----------外观模式;

1.说白了就是门面,为子系统的一组接口提供一致的界面

2.不仅简化了组件系统的接口而且也达到了一种解耦效果。

3.外观:简化接口;适配器:转化接口;桥接:分离接口与实现(两个维度);装饰:有稳定接口的前提下为对象扩展功能;

----------享元模式:

1.表面似乎和单例达到效果差不多,但有区别的。

2.主要解决因大量细粒度的对象会充斥整个系统,占用大量内存;

3.当对象被频繁使用时,可以把他们聚合起来,成为共享的,当再次调用,直接调用,不必重新new;

4.案例,保姆公司,提供不同保姆案例

5.注意分辨外部状态(比如传参)和内部状态(共享的)

6.降低系统对象的个数,降低内存压力;但使复杂程度增加;

7.考虑是否值得,当对象太少的话,而使用享元得不偿失;

----------代理:

1.为其他对象提供一种代理以控制对这个对象的访问;体现了一种封装思想;

2.代理,与适配器区别:代理主要是控制对对象访问的复杂度;

3.比如webservice中有代理类,封装了网络数据传输解析等,而使得访问特别方便;

----------以上结构型完毕

----------模板方法:

1.动机:对于某一项任务,常常有稳定的整体操作结构,但子部分有很多改变的需求;

2.它是子类可以不改变一个算法的结构重定义该算法的某些特定步骤。

3.父类封装了固定算法方法,并定义子虚方法,儿子类实现父类重写虚方法达到变更步骤细节效果。

4.比如造房子步骤都一样的,把步骤顺序和步骤抽象出来,让各种类型房子实现即可,不变的是步骤,变  化的是步骤内部的东西,而这些由子类来重写;

5,三层中可使用模板,针对sql和orical;

6.一次性实现一个算法的不变部分,将可变的行为留给子类来实现。子类的公共行为应该提取给父类,防止重复;

7,实际是钩子思想(虚方法或抽象方法)

-----------命令模式:

1.动机:行为请求者和行为实现者呈现一种紧耦合,比如页面按钮点击事件;

2.意图:将一个请求封装为一个对象,将行为对象化,使得可操作,比如排队、撤销;

3.将命令行为抽象成对象,而这个对象负责执行传过来对象的某种行为,这样再聚合一系列的命令对象,

  这样便可以让命令排队,撤销,全部执行等操作;

4.可以是多个请求进行记录、排队、撤销、同意执行;命令可以将状态保存;

5.比如迅雷的多文件下载;

6.将命令序列化,惊醒网络传输;

7.组合模式+命令模式=符合命令;层层执行;

8.过多的命令,就是这种模式不切实际;

9.和委托类型,注意区别;命令更加严谨;

------------解释器(很少使用,还有享元)

1.动机:某一特定领域的问题比较复杂,类似的谋士不断重复出现。

2.可以把重复出现的行为抽象出来形成特定的语法规则;

3.定义一种解释器,来解释语言中的句子;

4.提供了一个简单的方式来执行语法,容易修改和扩展语法;

5.实际就是将解释过程、转换过程抽象出来而已。

------------mediator中介者:

1.多个对象相互交互会有复杂的引用关系,但遇变更很难更改;难以重用复用;

2.可以是一个中介对象来管理这种交互,好比公司找员工,员工找公司,就会错综复杂,如果

双方都照中介的话,有中介交互,就有多对多转化为了一对多,和一对多关系。

3.达到一种松散耦合目的;

4.案例:国家和联合国的关系;

5.将多个对象间复杂的关联关系解耦,将多对对关联,转变为了多对一个终结者关联;

7.终结者,聚合多有对象,当一个对象要通知其他对象时,遍历即可;

------------iterator迭代器;

1.对于一个集合,我们关心的第一,数据存储结构第二遍历数据;

2.为了不违背单一职责原则,将遍历行为分离出去;

3.抽象出一个迭代类负责,既不暴露集合内部结构,又能是外面访问。开闭原则;

4.1.顺序访问集合元素2.不暴露对象内部;

5.集合对象对外提供一个迭代器类;集合对象类和迭代器类之间是双向应用;

6..net:非泛型和泛型:IEnumerable接口返回一个IEnumerator(提供多的迭代器);

7.foreach迭代器原理,在使用foreach,集合应该是只读的,不应该在内部做相应的操作。应该使用

for循环;

-----------职责连模式:

1.动机:一个请求可能被多个对象进行处理,但是每个请求在运行时只能有一个接受者,如果显示

的指定,就会形成紧耦合;

3.比如员工请假,根据请假天数,层层往上传递申请;

4.适用场合:一个请求可能有多个接受者,但最后真正接受者只有一个。

5.职责连目的是将请求发送者和请求接受者解耦;可动态添加修改请求的接受者

-----------观察者(*)

1.体现一种通知依赖关系;

2.定义对象间的一对多依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知

并自动更新。

3.被观察这聚合观察者,而观察者又关联被观察者。

4.注意.net中事件委托,委托充当了抽象的observer接口,而提供事件的对象充当了目标对象。

-----------备忘录

1.让人想起游戏进度保存进度读取,

2.动机:对象的状态在转换过程中需要回溯之前某个状态;

3.如何实现对象的状态的良好保存和回溯,但又不会因此破坏对象本身的封装性;

4.实际上是将状态保存到对象中,然后在由管理者聚合这些状态,根据标识存取这些对象;

-----------状态

1.动机:如何在运行时根据对象的状态来透明的更改对象的行为;而不为对象的操作和状态转化引入紧耦合。

2.允许一个对象在其内部状态改变时,改变他的行为,貌似是不同的对象;

3.表现为将状态抽象,而将不同的行为放在子对象中。

4.将所有与一个特定状态的相关的行为放入一个state的子类,在对象状态切换时,切换相应的对象,同时

维持state的接口,这样实现了具体的操作与状态转换之间的解耦。

----------策略:

1.某些对象使用的算法可能多种多样,经常改变。直接写到对象中有些复杂。

2.如何在运行时,来动态改变算法。

3.定义一系列算法,把它们一个个封装提来,并使他们相互替代(状态有些类似吧)

----------访问者:最后一种:

1.再不改变类的层次结构的前提下透明的为类层次结构(被访问者)上的各个类动态的添加新的操作。

2.表现为,调度这聚合被访问的对象,之后遍历对象接受访问者的访问,对象在接受

访问时,把自己关联到访问者的内部。

3.体现的是双向关联,通过双重分发来实现在不改变对象类层次结构的前提下,在运行时

透明的为类层次结构上的各个类动态添加新的操作。

4.缺点:一旦对象结构类发生改变,比如增加,那每一个访问者都必须得到通知。代价很大

原文地址:https://www.cnblogs.com/guozefeng/p/3334085.html