三大特性:
封装,继承,多态。
原则;
单一职责原则
开放-封闭原则:开放---->软件可以扩展,封闭------>但是原有代码不可修改。
依赖倒转原则:高层模块不应该依赖底层模块,两个都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
迪米特法则:前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。
里氏代换原则:子类型能够替换掉他们的父类型。一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且软件实体察觉不出父类对象和子类对象的区别,也就是说在软件里面,把父类都替换成它的子类,程序的行为没有变化。
合成/聚合复用原则(CARP):尽量使用合成/聚合,尽量不要使用类继承。
聚合是什么意思呢?聚合表示一种弱的拥有关系,比如A对象可以包含B对象,但是B对象却不是A对象的一部分。
合成是什么意思呢?合成表示一种强的拥有关系,打比方说:
大雁有两个翅膀,翅膀与大雁是部分和整体的关系,并且他们的生命周期是相同的,所以大雁和翅膀就是合成关系。
大雁是群居动物,那么单独一只大雁是属于雁群的,一个雁群可以有多只大雁,所以大雁和雁群是聚合关系。
高内聚,低耦合
面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
策略模式:用来封装算法的,实践中可以用来封装几乎任何类型的规则,只要在分析过程中需要在不同的时间应用不通的业务规则,就可以考虑用策略模式处理这种变化,适用于经常改变算法的场景。
装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。(可以理解为人是一个对象,衣服,鞋子,领带这些都是功能,人穿衣服鞋子等来装饰自己)。此模式是为已有功能动态的添加一种新功能或者多种新功能的方式,而这些新增的功能仅仅是为了满足一些只在特定情况下才会执行的需要,这时候就适合于装饰模式。
代理模式:为其他对象提供一种代理,用来控制对此对象的访问。顾名思义就是为一个对象代理,一般是和代理对象有共同的父类,代理和代理对象同时实现父类的接口,但是再代理实现接口的函数里new 出代理对象,来实现代理功能。
模板模式:
1.定义一个操作中的算法骨架(流程),然后将某些一部分的接口由子类来实现(也就是说父类中有些接口自己实现了,其它抽象的接口就由子类来实现),这样就可以在不改变一个算法的接口前提下重定义该算法的某些步骤接口。
2.通过把不变行为由父类来实现,这样就可以去除子类中重复的代码,特别是当不变的行为和可变的行为在子类实现中混合在一起的时候,不变的行为就会在子类中重复出现,通过模板模式把这些不变的行为搬移到父类中吗,帮助子类摆脱重复的不变行为代码。
外观模式:
基本上主要是大项目都会使用上,首先在设计初期阶段,要有意识的将不同的层分离,比如经典的三层架构,需要在数据访问层和业务逻辑层,业务逻辑层和表示层的层与层之间建立外观Facade,使得耦合度降低,其次在开发阶段,子系统因为不断的重构演化变得越来越复杂,增加外观Facade可以提供一个简单的接口,减少他们之间的依赖。第三是在维护一个遗留的大型系统(这里的系统指的是一整套类代码)时,这个系统已经非常难以维护和扩展了,但因为新的需求又要依赖于他,此时可以为新系统开发一个Facade类,把高度复杂的遗留代码接口的交互工作都在这个Facade类中处理,让新系统和Facade对象交互。
ps:这里说的子系统或者系统可以是一个单独的类,也可以是多个类的集合。
建造者模式:
是为创建一个产品对象的各个部件指定的抽象接口,然后由其子类来具体实现各个部件功能,然后创建一个创建者类来实现一个具体步骤的接口。
观察者模式:
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当这个主题对象状态发生变化时,会通知所有观察者对象,是他们能够自动更新自己。那什么时候应该使用呢?当一个对象的改变需要同时改变其他对象的时候,并且实际项目中,具体的观察者完全有可能是风马牛不相及的类,所以需要给它们提供一个统一的update()函数接口来操作。
状态模式:
主要解决的是当控制一个对象状态转换的条件表达式过于复杂时(比如在类中的一个成员函数中if else判断语句过多过长),把状态的判断逻辑转移到表示不同状态的一系列类当中,从而把复杂的逻辑判断简化,如果这个状态判断很简单就没必要用此模式了。比如你有一个判断逻辑 if .....else if ......else if ...............else,这个判断很长,这时候就可以用状态模式把这些分支变成一个又一个的类,增加时不会影响其他类,然后状态的变化在各自的类中完成,这样就可以消除庞大的条件分支语句。
适配器模式:
将一个类的接口转换成客户希望的另一个接口。何时使用适配器模式呢?当你想使用一个已经存在的类,但如果他的接口和你要求的接口不相同时,就应该考虑适配器模式。
备忘录模式:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。也可以用clone的方式(似乎也是一种设计模式)来实现备忘录,但是clone是开放了所有的public接口。
桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立的变化。什么叫抽象与它的实现分离?这并不是说,让抽象类与其派生类分离,而是抽象类和它的派生类用来实现自己的对象。
当我们多角度去分类实现对象,发现用继承或造成大量类的增加的时候就要考虑桥接模式了。
命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
适用场景:有多个对象可以处理同一请求,具体哪个对象处理由运行时刻自动确定。比如说请假流程或者说申请加薪流程。个人感觉用职责链模式如果稍加不注意很容易出现段错误并且容易绕。
中介者模式:将一个系统分割成许多对象通常可以增加其可复用性,但是对象间相互连接的激增又会降低其可复用性了?这是因为大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体了,所以,对系统的行为进行任何较大的改动就十分困难了。这时候中介者模式的作用就体现出来了。
具体定义为:用一个中介对象来封装一系列的对象交互,中介者是各对象不需要显示地相互引用,从而是其耦合松散,而且可以独立的改变他们之间的交互。中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合。
由于中介者模式定义的中介者类控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得中介者会变得比其他类更复杂,所以一旦这个类出了问题,整个系统都会有问题。
享元模式:共享代码,运用共享技术有效地支持大量细粒度的对象。享元模式可以避免大量相似类的开销。
应用场景:如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的开销时就应该考虑使用,还有就是对象的大多数状态是可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。PS:个人感觉享元模式就是用来出来使用了大量对象造成开销很大的时候来使用的。