一.前言
几个月前的看书笔记,内容全部都是摘自书中比较精辟的句子。笔记都是一段一段的句子,故没有文章的篇幅概念,仅供温习之用,更多详细内容请看原书!!!
<代码整洁之道>里面有很多前人编写简洁、漂亮代码的经验。当然书中作者的经验并不100%适合每个人,但大部分都是可借鉴的!
<java与模式>这本书内容太多了,我看的pdf有一千多页,有些粗略看了一下,做的笔记有点少。书中内容都很详细,值得反复读看!
<head first设计模式>是head first系列书籍,该书籍喜欢用图片和案例场景来讲解每个模式的应用场景,还有很多生动有趣的对白,增加读者对知识的记忆!
最后,个人觉得模式只是一种解决问题的思想,并不只拘泥于java语言。多拓展自己的广度,总会有好处,经历即财富!
二.代码整洁之道笔记
要写整洁的代码,必须先写肮脏代码,然后再清理它
没什么比糟糕的代码给开发项目带来更深远和长期的损害
糟糕的代码会无情地拖着团队的后退
检查对象或者方法是否想做的事太多.如果对象功能太多,最好切分为多个对象,
如果方法功能太多,就使用抽象重构之.
减少重复代码,提高表达力,提早构建简单抽象.
光把代码写好可不够,要保持代码的整洁.代码会随着世界的流逝而腐坏.
清理代码不一定要花多少功夫,也许只是改一个变量,拆分一个有点过长的函数,
消除一点点重复代码,清理一个嵌套的if语句
命名不要出现数字.如:var1,var2,fun1(),fun2()
命名不能混淆,如ProductInfo和ProductData.2个基本可认为一样的东西,不要同时出现.
还有,如:getAccount(),getAccounts(),getAccountInfo().这3个不要同时出现,会产生误导.
缺少明确约定
不要自己拼造单词,你拼造的单词,别人不一定会懂
如:genymdhms(),这种不容易识别.改成generationTimestamp()会比较好;生成时间戳
长名称胜于短名称,搜得到的名称胜于自己拼造的名称.
不要害怕长名称.长而具有描述性的名称,比短而令人费解的名称好的多.
长而具有描述性的名称比描述性的注释好的多
类名和对象名应该是名词和名词短语,如:Customer,Account,避免Manager,Processor
方法名应当是动词或动词短语,如:postPayment,deletePage
给每个抽象概念选一个词,如:使用fetch,retrieve,get来给在多个类中的同种方法命名
不要一语双关,如:add()是用来计算2个值的+运算,就不能用add()来表示集合的添加,应该用insert(),或者append()
添加有意义的语境,如:firstName,lastName,street,city,state,这些变量放到一起就是一个地址
如果,state单独看,就不知道是地址,这个时候可以添加前缀,addrFirstName,addrLastName,addrState
更好的方案是创建一个Address类
函数最好只做一件事,函数要短小精悍.判断是否只做一件事,看是否能再拆出一个函数
函数的参数,最理想的是零参函数,其次是一参函数,再次是二参函数
二参函数适合自然对参数,比如坐标new Point(x,y)
如果需要2个,3个或者3个以上,说明其中一些参数应该封装成类
如:创建圆,Circle makeCircle(double x,double y,double radius)
可以改成Cicle makeCircle(Point center,double radius)
如果函数必须要修改某种状态,就修改所属对象的状态
try/catch块里面的主体部分,最好抽离成一个单独的函数
catch/finally后面不该有其他内容
依赖磁铁.如:一个错误枚举类public enum Error{OK,INVALID,NO_SUCH;}
其他类如果要使用它,都要导入它,如果Error类修改,其他所有类都要修改,部署
可以用异常来代替错误类,新异常类可以从异常类派生出来,无需从新部署,编译
别给糟糕的代码加注释,重新写吧
如果你发现自己需要写注释,再想想是否可以翻盘,用代码来表达
不准确的注释要比没注释坏的多,只有代码会告诉你真正做什么
写注释的唯一动机就是有糟糕代码的存在
如:
//Check to see the employee is eligible for full benefits
if((employee.flags & HOURLY_FLAG) & (employee.age > 65))
可以改成
if(employee.isEligibleForFullBenefits())
代码的归属与署名,/*Added by yuu*/.这种不要自己去添加,由版本控制器来管理
不要在项目中留下注释代码(个人觉得,调试期可以留),版本控制器会记住曾经的代码
若某个函数调用了另一个函数,就应该把它们放到一起,调用者应该尽可能放在被调用者上面
这样能轻易找到被调用的函数
每行的字符上限最好不要超过80到120
函数名和左圆括号之间不要空格,函数参数之间用逗号隔开,并用空格分开
不要写火车代码,如:String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
最好分开写
Options options = ctxt.getOptions();
File scratchDir = options.getScratchDir();
String outputDir = scratchDir.getAbsolutePath();
如果代码涉及到路径,代码里面最好不要用斜杠,点号,扩展名
应该用常量代替
代码用尽量少用!=null这种判断
如:某个get方法返回一个集合,判断一个集合是否为空,然后再对集合操作
改成:get方法直接返回一个空集合,那么就不用判断是否为空,代码会看起来整洁
函数传值最好不要传入null,会产生一些糟糕的情况,多余的判断代码,或者异常的产生
同一个函数中,相关连的代码挨在一起,不怎么相关的最好用一行空格分开
类中,如果有公共静态常量,应该先出现,然后是私有静态常量,以及私有实体变量.很少会有公共变量
公共函数应该出现在这些变量之后.公共函数调用的私有函数,最好放在改公告函数的后面
要符合自顶向下原则.
类的封装最好私有化.放松封装总是下策.
类跟函数一样,最好要短小精悍.类的名称应当描述其权责.
一个类不应包含太多的权责
鉴别权责常常帮助我们在代码中认识并创建出更好的抽象
在一个系统中分出很多短小的类,不要认为要搞清楚项目的原理
会在类中找来找去.然而每个达到一定规模的系统都会包含大量的逻辑性和复杂性
管理这种复杂性首要目标是加以管理,以便开发者知道要在哪儿能找到东西
这就体现单一权责原则
类应该只有少量的实体变量.通常函数操作的变量越多,就越黏聚到类上.
如果一个类中每个变量都被每个函数所是使用,那么该类具有最大的内聚性.
类的内聚性高,意味着类中的方法和变量相互依赖,相互结合成一个逻辑整体.
将函数拆分为许多小函数,也就是将类拆分成很多小类的时机
程序会更加有组织,会拥有更加透明的结构
类应该对扩展开发,对修改封闭.体现开发-闭合原则
代码不可重复,有些类似的代码也可以重构
int isSize(),boolean isEmpty()
可以改成
boolean isEmpty()
{
return isSize() == 0;
}
对象是过程的抽象,线程是调度的抽象
线程错误不要归咎于偶发事件
编写可插拔现场代码,这样就能在不同的配置环境下运行
编写可调整的线程代码,如允许线程数量的调整
不同操作系统有着不同的线程策略,应尽早经常在目标平台上运行线程代码
遵循单一权责原则.将系统分离线程相关的代码和线程无关代码的POJO
不要锁定不必要的代码,避免从锁定区域调用其他锁定区域
代码里面最好不要出现数字,字符串.应该用变量或者常量代替
不恰当的,废弃的,冗余的糟糕的注释,注释掉的代码是不应该存在的
如:i++; //increment i 这种注释没没必要,代码已经充分描述了自己
函数的参数应该少,boolean参数最糟糕,因为它告诉函数不只做一件事
死函数,永远不要调用的函数应该废弃.
代码的边界行为.每种边界行为都有可能会扰乱代码.
每次看到重复的代码,意味着遗漏了抽象.重复的代码可能成为子程序或者干脆是另一个类.
将重复的代码叠放进类似的抽象.其他程序员可以用到你创建的抽象设施
较隐藏的形态是,在不同的模块中不断检查switch/case,if/else块.可以用多态来代替之.
所有较低层级概念放到派生类中,所有较高层级概念放到基类中
如:与细节有关的常量,变量或工具函数不应该出现在基类中.基类应该对这些东西一无所知
这条规则对源文件,组件和模块也使用.良好的软件设计要求分离位于不同层级概念.将他们放到不同的容器中.
有时,这些容器是基类或派生类,有时是源文件,模块或组件.无论哪种情况,分离都要完整.
设计良好的模块有着非常小的接口,让你事半功倍.
优秀的软件开发会限制类或模块中暴露的接口数量.类中方法越少越好.函数知道的变量越少越好
类拥有的实体变量越少越好.隐藏你的数据.隐藏你的工具函数.隐藏你的常理和临时变量.
不要创建拥有大量的方法或大量实体变量的类.不要为子类创建大量受保护变量和函数.
尽力保持接口的紧凑.通过限制信息来控制耦合度.
死代码就是不执行的代码.可以检查不会发生的条件的if语句,从不抛出异常的try/catch语句
永不发生的switch/case条件.死代码尽早删掉
本地变量应该正好在其首次使用的位置上面,垂直距离要短.
用多态代替if/else,switch/case语句
避免否定性条件
if(buffer.shouldCompact())要好于if(!buffer.shouldNotCompact())
函数只做一件事,如果不只做一件事应该分离为多个小函数
避免传递浏览.如果A与B协作,B与C协作.我们不想让使用A的模块了解C的信息
就是避免a.getB().getC().doSomething();这样的代码
import代码包,最好使用通配符号.过长的导入清单会令读者望而却步.
指定导入包是一种硬依赖,而通配符号不是.
不要继承常量,常量躲在继承机构的顶端会难以跟踪.
应该用静态导入
import static ClassName.*
比起常量,最好用enum.枚举有方法和字段,提供更多的表达力和灵活性.
不要太快取名,确认名称具有描述性.事物的意义随着软件的演变而变化.
名称要与抽象层级相符合
尽可能使用标准命名法.如:java中,将对象转换成字符串的函数通常命名为toString().最好遵循这些约定.而不是自己创造命名法.
不要编码,类似m_或者f之类的前缀完全是多余的.当今的开发环境下不用纠结前缀.
不要用匈牙利命名法
名称要说明副作用.如:getObject(),如果里面判断对象为空就创建一个对象.所以命名应该是createOrReturnObject()
尽量不要继承具体类,应该继承抽象类.
在一个继承关系形成的等级结构里面,树叶节点均应当是具体类,而树枝节点均应当是抽象类或者java接口.
假设有2个具体类,类B是类A的子类,那么最简单的重构方案就是建立一个抽象类C.让类A和类B成为抽象类C的子类.
这样的设计是所有java设计师都应当努力做到的.
在一个继承的等级结构中,共同的代码应当尽量向等级结构的上方移动.
把重复的代码从子类移动到超类里面,提高代码的复用率.
但数据的移动,要从超类移动到子类.一个对象的数据不论是否使用都会占用资源.因此数据应当尽量放到具体类或者等级结构的低端.
不要从工具类去继承,工具类没有分类学的意义
使用多个专门的接口比使用单一的总接口要好.
将没有关系的接口并在一起,形成一个臃肿的大接口,是对接口的污染
任何一个实体,除非绝对需要,不然不要与外界通信.
即使必须要进行通信,也应当尽量限制通信的广度与深度.
定制服务原则.客户端仅仅需要某一些方法或者接口,那么就只为客户端提供这些需要的方法或者接口.
向客户端提供的public接口是一种承诺,一个public接口一旦提供,就很难撤回.
过多的承诺,或者没有必要的承诺会给系统的维护造成不必要的负担.
当一个类是另一个类的角色的时候,不应当使用继承描述这种关系.
如:雇员,经理,学生.他们是人类的一个角色,一个人可以同时有3种角色
三.java与模式笔记
迪米特法则.
一个对象应当对其他对象有尽可能少的了解.
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用.
如果其中的一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用
依赖倒转原则可以克服狭义的迪米特法则的缺点.
使不必彼此直接通信的类变为抽象类型.
类的划分上,应该创建弱耦合的类.类之间的耦合越弱,就越有利于复用.
一个处于弱耦合中的类一旦被修改,不会对有关系的类造成波及.
尽量降低一个类的访问权限.尽量降低一个类成员访问权限.优先考虑private.
静态工厂方法是为了将具体子类实例化的工作隐藏起来.
从而客户端不必考虑如何将具体子类实例化.
将工厂方法的返回类型设置成抽象产品类型的做法,叫做针对抽象编程,这是依赖倒转原则的应用.
工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上.
工厂方法模式有一个别名叫多态性工厂模式.这个模式完全支持开放闭合原则.
工厂方法返回的应该是抽象类型,而不是具体类型.丧失多态性后,就不再是工厂方法了.
工厂方法模式中只有一个产品等级结构
抽象工厂模式比工厂方法模式更灵活,对应的需求更复杂.
抽象工厂模式有多个产品等级结构
包含的角色:抽象工厂角色,具体工厂类角色,抽象产品角色,具体产品角色
一个具体工厂类对应一个具体产品族,一个产品族由多个同等级层具体产品类组成.
相图里面,横坐标代表等级结构,纵坐标代表产品族
建造模式:有多少零件就有多少方法.
每个产品类,就有一个相应的具体建造者类.
每个产品里面有若干零件,每个零件对应具体建造类一个建造方法.
默认适配器模式.用抽象类去实现接口,再用具体类去继承抽象类.
这样就可以选择性实现接口里面的方法.
适配器模式的用意是改变所考虑的对象的接口而不一定改变对象的性能.
装饰器模式的用意是要保持接口,从而增强所考虑对象的性能.
装饰器模式将一个东西的表皮换掉,而保持它的内心.
适配器模式和装饰器模式都是包装(wrapper)模式.
适配器模式是把一个API转换成另一个API,而装饰器模式是保持被包装的对象的API.
一个装饰器类实现的新方法越多,它离纯装饰器类越远,离适配器模式越近.
装饰器模式有透明和半透明两种.
透明的装饰器模式也就是理想的装饰器模式,要求具体的构件角色,装饰器的接口与抽象构件角色接口完全一致.
半透明的装饰器模式中,装饰器角色的接口比抽象构件角色的接口宽,也就是里面的方法增加了.
半透明的装饰器模式实际处于适配器模式与透明装饰器模式之间.
装饰器模式应当为所装饰的对象提供增强的功能,代理模式对对象的使用施加控制,并不提供对象本身的增强功能.
享元模式里面,有单纯享元对象,复合享元对象.
复合享元对象里面有个集合,集合里面装着很多单纯享元对象.
复合享元对象是不可共享的.
享元模式的优点在于大幅度降低内存中对象的数量.
但享元模式使得系统更加复杂.为了使对象共享,需要将一些状态外部化,使得程序的逻辑复杂化.
不变模式要求一个对象的内部状态在创建之后就不再变化.
享元模式仅仅要求享元的内蕴状态变化不影响共享.
不变模式对一个对象要求强一点.
桥梁模式是将抽象化与实现化脱耦,使得二者可以独立地变化.
桥梁模式个人理解:例如一级抽象A持有一级抽象B的引用,二级抽象A1和二级抽象A2继承一级抽象A.
二级抽象B1和二级抽象B2继承一级抽象B.
多态的性质,二级的A和B对象可以相互联系,当新增加二级A3,二级B3时,可以不用改变原来的类,一样可以相互联系.
找到系统的可变因素,将之封装起来,叫做对变化的封装.是达到开闭原则的途径.
桥梁模式是对变化的封装.封装到继承的等级结构中.
不变模式里面.不变对象要比可变对象更加容易维护.
没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的.
大多数享元对象是不变对象.
策略模式把行为和环境分开.
环境类负责维持和查询行为类,各种算法则在具体的策略类中提供.
环境和算法独立开后,算法的修改不会影响环境和客户端.
策略模式相当于可插入式的算法.
策略模式不适合处理多于一个算法的情形.只适用于客户端的几种算法中选择一种情形.
如果想同时让客户端选择一种以上的算法,可以配合装饰器模式.
如果一个对象有很多行为,可以用策略模式来代替难以维护的多重条件选择语句.
策略模式使用委派的方法提供不同的算法行为
模板方法模式使用继承的方法来提供不同的算法行为.
MVC模式里面的视图-控制器关系就是典型的策略模式例子.
模板方法.在抽象层提供某些具体方法和抽象方法,让子类去实现抽象方法来具备不同的功能.
观察者模式在java语言里有支持.java.util库里面,提供了一个Observable类以及一个Observer接口.
命令模式.把发送命令的对象和接受命令的对象分开.
命令对象里面持有接受命令的引用,接受命令的对象才是真正的命令执行者
发送命令的对象里面有命令对象的引用,间接与接受命令对象联系.
备忘录模式.
发起人对象,创建新备忘录对象,恢复备忘录对象,修改,获取状态
备忘录对象,里面存有状态
负责人对象,对备忘录对象的存储和返回.
备忘录对象的责任:将发起人对象的内部状态存储起来.
备忘录对象可以保护其内容不被发起人对象之外的对象读取.
备忘录模式可以使用双重接口来实现黑箱备忘录模式.
黑箱备忘录模式.发起人对象可以把备忘录对象封装,符合设计思想.
网站的cookie运用也是备忘录模式.
cookie便是备忘录角色,网站是发起人角色.
系统配置文件,存有用户的偏爱,视图位置,这也是备忘录模式.
状态模式.当一个对象的行为依赖于它所处于的状态,对象的行为必须随着其状态的改变而改变.
对象在某一个方法里依赖于一重或多重条件语句,其中有大量的代码.状态模式把条件语句的
每一个分支都包装到一个单独的类里.维护这些独立的类就不再影响到系统的其他部分.
TCP的链接状态便是状态模式的应用.
状态模式和策略的模式的区别.
一旦环境选择了一个具体策略类,那么在整个环境类的生命周期里它都不会改变这个具体策略类.
而状态模式则适用于另一种情况,及环境角色有明显的状态转移.在环境类生命周期里面
会有几个不同的状态对象被使用.
还有一个区别,策略模式的环境类会自己选择一个具体策略类
状态模式的环境类是被外在原因放进一个具体状态中.
java语言通过方法重载支持静态多分派,通过方法覆盖支持动态单分派.
一个方法重载和一个方法覆盖可以实现混合的双重分派.
访问者模式即实现动态双重分派.
如果系统的数据结构是频繁变化的,则不适合使用访问者模式.
访问这模式增加新的节点很困难.会破坏封装.
过多使用重载会使一个系统变得复杂,难以维护.
调停者模式是迪米特法则(只与你直接的朋友通信)的一个具体应用.
调停者模式可以避免对象之间的过度耦合.
调停者模式与门面模式很相似,不过门面模式的消息传送是单方向
调停者模式消息传送是多方向.
四.Head First设计模式笔记
模式就是在某种情况(context)下,针对某问题解决方案.
模式是发现的,不是创建的.任何人都可能发现莫个设计模式,然后写出它的描述.
模式虽然好.但不一定是万能的.有时候一个简单的解决方案比模式好的多.
不要让模式过度影响人的决策.过度使用设计模式可能会导致代码被过度工程化.
注意要折中.
设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起.
以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的部分.
设计原则:针对接口编程,而不是针对实现编程.
设计原则:多用组合,少用继承.
对象的行为不是继承而来,而是和适当的行为对象组合来的.
使用组合建立的系统更有弹性.
松耦合的设计之所以能让我们建立有弹性的OO系统,能应对变化.
是因为对象之间的相互依赖降到了最低.
设计原则:类应该对扩展开放,对修改关闭.
设计原则:要依赖抽象,不要依赖具体类.
工厂方法用的是继承.抽象工厂用的是对象的组合.
工厂方法创建对象需要扩展一个类,并覆盖它的工厂方法.
抽象工厂,要想使用工厂,必须实例化它,然后将它传入一些针对抽象类型中.
优点是可以把一群相关的产品集合起来.
所有的工厂都是用来封装对象的创建.
聚合关系,A聚合到B上,或者说B由A组成.用空心的菱形
一个部门由许多人员构成.没有依赖关系没有组合强.没有部分后,人员依然存在.
组合关系,用实心的菱形.
A组合成B,或者说B由A组成.
组合关系是一种强依赖的特殊聚合关系,如果整体不存在,部分也消亡.
如母公司解体,子公司也不会存在.
节点是带有至少一个处理器,内存以及可能还带有其他设备的处理元素.
一般来说服务器,工作站或客户机都可以称为一个节点.节点是应用程序的部署单元.
命令模式:发出请求的对象和执行这些请求的对象分开.
适配器模式分为对象适配器和类适配器.
对象适配器使用的是组合.类适配器使用的是继承.
类适配器要用到多继承,java不支持.所以一般用对象适配器.
适配器模式的意图是:改变接口符合客户的期望
门面模式的意图是:提供子系统的一个简化接口.
提供一个统一的接口,用来访问子系统中的一群接口.
当需要使用一个现有类而其接口不符合你的需求时,就使用适配器模式.
当需要简化并统一一个很大的接口或者一群复杂的接口时,使用门面模式.
设计原则:只和你的密友谈话.减少对象之间的依赖.
模板模式.定义了算法的步骤,把这些步骤的实现延迟到子类.
模板方法模式为我们提供了一种代码复用的重要技巧.
模板方法的抽象类可以定义具体方法,抽象方法,钩子.
抽象方法由子类实现.
为了防止子类改变模板方法中的算法,可以将模板方法声明为final
模板方法模式使用的是继承,策略模式使用的是组合.
工厂方法是模板方法的一种特殊版本.
迭代器模式让我们能遍历聚合内没一个元素,而又不暴露其内部表示.
把遍历交给迭代器,而不是聚合对象.
设计原则:一个类应该只有一个引起变化的原因.
这个原则告诉我们,将一个责任指派给一个类.
组合模式让客户对个别对象以及组合对象一视同仁.
组合结构内任意对象称为组件,组件可以是组合,也可以是叶节点.
状态模式和策略模式有相同的类图,但它们的意图不同
策略模式通常会用行为或算发来配置context类
状态模式允许context随着状态的改变而改变行为
代理模式为另一个对象提供代表,以便控制客户对对象的访问.
代理模式有很多种:缓存代理,同步代理,防火墙代理.
代理在结构上类似装饰器模式,但是目的不同.
装饰器是在对象上面家行为,而代理是控制访问.
MVC模式是复合模式,结合了观察者模式,策略模式和组合模式.把MVC三层解偶
MVC中.控制器把控制逻辑从试图中分离,让模型和视图之间解偶.
模型用观察者让控制器和视图可以随最新的状态改变而更新
同一个模型可以使用不同的视图,甚至可以同时使用多个视图.
视图和控制器则实现了策略模式.策略模式可以让视图和模型之间解偶.
控制器是视图的行为,如果希望有不同的行为,可以直接换一个控制器.
视图内部使用组合模式来管理窗口,按钮以及其它显示组件.
装饰器模式:包装一个对象,以提供新的行为.
状态模式:封装了基于状态的行为,并使用委托在行为之间切换.
迭代器模式:在对象的集合之中游走,而不暴露集合的实现.
外观模式:简化一群类接口.
策略模式:封装可以互换的行为,并使用委托来决定要使用哪一个.
代理模式:包装对象,以控制对此对象的访问.
工厂方法模式:由子类决定要创建的具体类是哪一个.
适配器模式:封装对象,并提供不同的接口.
观察者模式:让对象能在状态改变时被通知.
模板方法模式:由子类决定如何实现一个算法中的步骤.
组合模式:客户用一致的方法处理对象集合和单个对象.
单例模式:确保有且只有一个对象被创建
抽象工厂模式:允许客户创建对象的家族,而无需制定他们的具体类.
命令模式:封装请求成为对象.
模式按照其目的可分为:创建型,结构型,行为型.
创建型模式与对象的创建有关,将对象的部分创建工作延迟到子类
结构型模式处理类或对象的组合,使用类继承的机制来组合类,描述了对象的组装方式
行为模式对类或对象怎样交互和怎样分配职责进行描述,描述一组对象协作完成单个对象所无法完成的任务.
按照范围可分为:类模式,对象模式.
类模式处理类和子类之间的关系,是静态的,编译时刻便确定下来
对象模式处理对象之间的关系,这些关系在运行时刻是可以变化的,更具有动态性.
创建模式:
Factory:工厂模式
Singleton:单例模式
Builder:建造模式
Prototype:原型模式
结构模式:
Facade:门面模式
Decorator:装饰模式
Composite:合成模式
Proxy:代理模式
Adapter:适配器模式
Bridge:桥梁模式
Flyweight:共享模式
行为模式:
Chain of responsibility:责任链模式
Command:命令模式
Strategy:策略模式
Observer:观察者模式
Interpreter:解释器模式
Iterator:迭代器模式
Mediator:中介模式
Memento:备忘录模式
State:状态模式
Template:模板模式
Visitor:访问者模式