Skip to content

wjire/Design-Pattern

Repository files navigation


观察者模式:
	定义了对象之间的一对多依赖关系.当一个对象改变状态时,它的所有依赖者都会收到通知.

========================================================================================================================================================

单例模式:
	什么情况下需要使用单例,我的理解是:
	当一个类没有任何字段或者属性的时候就可以使用单例.因为没有字段和属性,意味着每个实例其实都一样,它们没有状态的区别,都仅仅是拥有相同的行为而已.但是,实际上这种类更应该做成静态类,而不是单例.单例更多的应该是用在需要保证一个类全局只有一种状态的情况.
	
========================================================================================================================================================

命令模式:
	感觉是调用者组合命令者,命令者组合接受者,从而实现调用者和接受者的解耦.感觉印证了那句话,能通过技术解决的问题,都可以通过包一层来解决.
	命令模式就好像是书记喊口号,他不管谁去做,怎么做,反正有人做就对了.
	加入使用"聪明"的命令对象,也就是说没有命令接收者,而是在命令对象中,直接实现了请求,那么就和平时最常用的 Handler 一样了.
	1.命令的发送者和命令的接受者实现了松耦合;
	2.命令可以随时扩展,只要继承 BaseCommand 即可;
	3.还可以撤销和恢复命令.

========================================================================================================================================================

外观模式:
	外观模式将客户和子系统解耦,通过封装子系统来提供一个简单的接口.
	外观模式是迪米特法则的典型应用.
	迪米特法则又叫最少知识原则:只和你的密友谈话.它减少了对象之间的依赖,这会减少软件的维护成本,但是这个法则有个致命的缺点:
	为了解耦,导致很多的"包装"类被制造出来,这个可能会导致复杂度和开发时间的增加,并降低运行时的性能.


适配器模式:
	所谓适配器模式,就是用一个中间件来对接两个不同的接口.
	既然是对接,就涉及到主动的一方和被动的一方.被动的一方通常叫做被适配的一方,既然主动方要"配合"被动方,那就得伪装一下.
	正所谓,能用技术办法解决的问题,都可以通过包一层解决.所以我们可以将主动方包装在一个适配器里面,让适配器去实现被动方的行为.
	当然了,在具体的行为实现里面,实际干的是自己的行为.只是被动方不知道而已.再简单点说就是,将主动方封装成一个继承自被动方的适配器.
	缺点:
	被动方有多少行为,适配器就必须实现多少行为.


装饰器模式:
	装饰器模式和适配器模式都是对对象的封装:
	1.装饰者的基类和被装饰者只是同一父类的不同子类;适配器和被适配者是同一接口的不同实现.
	2.适配器不关心行为的具体实现,主动去适配的一方,可以有任意的实现;而每一个装饰器都不知道传给他的对象是否已经被装饰过了,或者被多少装饰器装饰过了.它负责给传入的对象添加上它的行为实现.
	但,二者实际区别还是很大:
	1.装饰器模式可以在运行时,动态的添加行为,强调的是行为的多样性.
	2.适配器模式并不是添加行为,而是隐藏了行为的具体实现;并且适配器的行为是静态的,程序运行起来后,它的行为就固定了,你只能适配特定的接口,而无法适配其他的口.适配器模式强调的是如何让行为适配.
	装饰是个形容词,强调的是外在表现;而适配是个动词,强调的是行为对接,二者都有明显的缺点:
	1.当需要很多行为时,装饰器的子类会非常的多.
	2.当被适配的接口的行为很多时,主动适配的一方则需要实现所有的行为.


代理模式:
	代理模式和装饰器模式很像,它们都是将对象包装起来,然后把调用委托给另外一个对象.比如,装饰器模式是把最终调用委托给了另外一个装饰者,代理模式是把调用委托给了代理对象,但是他们的目的不一样.
	1.首先,一个是代表对象,一个是装饰对象;
	2.首先装饰者对外面是可见的,而代理者是透明的,外界不知道代理者是代理者,外界以为代理者就是真实对象;
	3.装饰器模式的目的是增加目标对象的行为,而代理模式看起来是增加了目标对象(真实对象)的行为,因为我们可以在调用真实对象的行为前做一些其他事情,但这些都发生在内部,对外界是透明的,外界以为这些就是真实对象的行为.所以这不能说是增加了真实对象的行为,而应该看做是对真实对象访问的控制.比如:延迟加载
	4.代理模式被归纳为结构型模式,而装饰器模式,适配器模式都属于行为模式,这就源自于它们的目的.结构型设计模式的出发点是对象,强调的是对对象的控制,而行为型模式出发点当然是行为了,强调的是对行为的控制.

	代理和适配器也很像,它们都是挡在其他对象的前面,并负责将请求转发给它们.不同的是,适配器会改变对象适配的接口,而代理则实现相同的接口.

适配器将一个对象包装起来,以改变其接口.
装饰者将一个对象包装起来,以增加新的行为和责任.
外观将一群对象包装起来,以简化它们的接口.
代理将一个对象包装起来,以控制对它的访问.


========================================================================================================================================================

工厂方法模式和抽象工厂模式:
	工厂方法模式强调的是产品的种类.是土豆,藕,西红柿还是青椒.
	抽象工厂模式强调的是产品族的品牌.是四川牌土豆,藕,还是山东牌土豆,藕.土豆+藕就是一个产品族,多种产品就叫产品族.它们都是四川工厂生产的.所以抽象工厂模式在工厂增加了产品种类,也就是产品族变化的时候,每个工厂都需要修改代码,这违法了"开闭原则".当抽象工厂的产品族只有一种产品的时候,其实它就退化成了工厂方法模式.
	   	 

模板方法模式:
	1.模板方法模式是在一个抽象类中定义一个操作中的算法骨架(对应于生活中大家下载的模板),而将一些步骤延迟到子类中去实现(对应于我们根据自己的情况向模板填充内容).模板方法使得子类可以不改变一个算法的结构前提下,重新定义算法的某些特定步骤,模板方法模式把不变行为搬到超类中,从而去除了子类中的重复代码。
	2.模板方法模式的一大亮点就是他的"钩子方法",当算法的某个部分是可选的,那就可以做成"钩子方法",让子类自己去选择.
	3.模板方法模式是创建框架时用得最多的模式,没有之一.
	4.工厂方法模式是一种特殊的模板方法模式.


策略模式:
	所谓策略模式,就是针对策略的模式,那策略是什么?按照日常生活中的解释,策略就是规则,算法,处理方法等.用OO思想解释,策略就是行为.
	日常生活中,策略往往会有很多,而我们需要在众多的策略中选择一种来执行,并且不同的环境下,我们选择的策略往往不一样,也就是说,我们选择的策略是会变的.
	而根据OO思想,我们需要将变化的地方独立出来,不能和那些不需要变化的代码混在一起.因此我们需要把策略,即变化的行为抽象出来.
	

策略模式和模板方法模式都是对算法的封装,不同的是:
1.策略用的组合,客户可以选择算法实现.并且组合是动态的,松耦合的.组合可以在运行时改变行为.因此组合更具有弹性.
2.模板方法用的是继承.继承是静态的,高度耦合的,但也是代码复用的一种技巧;



状态模式:
   * 每个对象都有其对应的状态,而每个状态都有一些相应的行为,如果某个对象有多种状态,那么就会对应很多行为,因此,对这些状态和行为的判断,会导致多重条件语,并且,如果要添加一种状态,则需要更改之前的代码,这显然违背了开闭原则.
   * 
   * 状态者模式就是来解决这种问题的,它将每种状态对应的行为抽象出来成为单独的新的对象,,这样状态的变化不再依赖于对象内部的行为.
   * 
   * 简单说,就是允许一个对象在其状态发生变化时,自动改变其行为.该模式强调"动态"二字,即状态变化时,行为会跟着变化,不需要调用者手动修改.
   *
   * 所以,该设计模式需要一个上下文环境来保存状态,也就是说需要将状态组合到上下文环境中.
   * 另外,关于状态的变化逻辑,则属于状态的具体行为,不属于上下文.那么,当状态变换时,就需要修改当前上下文环境中保存的状态,因此,状态对象里面还需要保存当前上下文环境.
   * 所以,状态和上下文环境的关系是"互相组合".

	一个对象在不同状态下的行为不一样时,就可以采用这种模式.
	将行为封装在状态中,这是一种典型的,非常经典的封装变化的思想.	如果不这么做,就意味着要写一大堆 IF ELSE.	


状态模式和策略模式很像,它们的类图一模一样,它们都是对行为的封装,都可以在运行时改变行为,不过它们改变行为的来源不一样.策略模式是因为外界环境的变化而改变行为,而状态模式是自身环境(内部状态)的变化而改变行为.一个是由外因改变,一个是由内因改变.


========================================================================================================================================================

迭代器模式
	为什么会有迭代器模式?
	因为一堆对象的数据结构表示有很多方式:数组,集合,链表,哈希等,但是他们各自的遍历方式都不一样,这就意味着调用者需要知道这一堆对象的具体表示是什么,或者说内部实现是什么.是数组?还是链表?又或者哈希?实际上,调用者不需要知道,他们只想每次得到那一堆对象中的一个就够了,管你内部是怎么组织的,所以我们需要这一堆对象的内部表示,这也是OO思想:封装细节.
	同时,我们也解耦了聚合对象和管理和遍历职责,把遍历的职责交给了迭代器,而自己则只专注管理对象.


组合模式:
	有两种实现方式:透明的和安全的.
	所谓组合模式,类似一个树,非叶子节点其实就是一个树,换句话说,一个节点如果有子节点,那它就是一个子树,如果没有,那它就是真的是个"节点".相当于,我们可以把节点添加到节点中,而我们让这两种节点都继承同一个基类,或者实现同一个接口.但是,问题来了,非叶子结点和叶子节点的行为是由差别的,比如非叶子节点可以删除,添加节点,还可以遍历等.而叶子结点就没有这些行为.所以实现方式就有两种了:
	1.透明的组合模式:基类定义所有的行为,那么在子类没有的行为实现里面,抛出异常或者什么也不做.这样的话,调用者不管考虑对象的真实类型,如果调用该节点的某个方法时,抛出异常则说明该方法不支持该行为.
	2.安全的组合模式:基类只定义共有的行为,具体的差异行为定义在具体的子类里面.这样的话,其实不好,虽然安全了,但是调用者如果想调用某个方法,还要判断一下对象的真实类型.
	所以,通常建议使用透明的组合模式.
	实际上透明的组合模式如果换个角度看,也是很合理的.比如,叶子结点不应该有删除,添加节点的行为,但是我们依然实现了它们,只是抛出了友好的异常,有些人觉得不应该这样,应该采用安全的组合模式.但是换个角度,我们可以把叶子节点看做是没有孩子的节点.
	

组合模式通常和迭代器模式一起出现,原因很简单,因为需要遍历组合对象的所有元素.


一些不常用的设计模式================================================================================================================================

桥接模式
建造者模式:
	1.客户端调用不同的构造器,即可获得不同的对象.然而对象的内部实现,内部构造过程对客户端来说则是透明的.
    2.建造者模式强调 复杂对象由其多个子对象按照一定的步骤组合而成.
    3.将一个复杂对象的构造与他们的表示分离,使得同样的构建过程可以创建不同的表示.
	4.与抽象工厂相似,区别是建造者模式强调的是步骤,如何一步步构造一个复杂的对象,而抽象工厂强调的是多个产品构成的产品族.一个强调的是过程,一个强调的是结果.

责任链模式
原型模式
解释器模式
中介者模式:多个类需要交互时,加入中介者,可以实现多个类之间的解耦;将来有新的类需要加入时,只需要在中介者类中增加额外的逻辑就行了.缺点是,中介者可能会过于庞大.
备忘录模式:当需要让对象返回之前的状态时,就可以使用该模式,比如"撤销".
访问者模式:





设计原则:
1.找出应用中可能需要变化之处 ,把他们独立出来,不要和那些不需要变化的代码混在一起;
2.针对接口编程,而不是针对实现;
3.多用组合,少用继承.继承的耦合度太高,组合则有更大的弹性.
4.为了交互对象之间的松耦合设计而努力;
5.类应该对扩展开放,对修改关闭;
6.依赖倒置原则:依赖抽象,不要依赖具体类.高层组件不能依赖低层组件,二者都应该依赖于抽象;
7.迪米特法则(最少知识原则):只和你的密友谈话;
8.好莱坞原则:决策权在高层手中:别调用我们(高层组件),我们会调用你(低层组件).这个原则和依赖倒置原则都是为了解耦,但二者的定位不一样:
	依赖倒置原强调的是多用接口/抽象类,避免使用具体类,更多的是系统中的类的设计原则;
	好莱坞原则强调的是系统中的框架的设计原则,让低层组件挂靠在高层组件中,而又不会让高层组件依赖低层组件.
9.单一职责原则:一个类应该只有一个引起变化的原因;

About

23种设计模式

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages