设计模式:(在软件设计过程中哪个地方进行使用,并且解决了什么问题) 处理软件设计中反复出现的问题

可扩展性 复用性 规范性 稳定性 可维护性 代码的可读性 灵活性 可靠性(高内聚低耦合)

遵守一套公共的设计模式

面向对象(oo) => 功能模块(设计模式 + 算法【树结结构】) => 框架 (使用多种设计模式) => 架构(服务器集群)

设计模式七大原则,23中设计模式

单一职责原则(对于类的设计每一个单一功能的类只处理一类问题) 举例说明(交通工具不同的运行方式) 方案一:对类进行拆分(写法比较松散,花销改动很大) 方案二: 增加方法(但是没有完全遵守单一职责原则。只是在方法级别进行遵守。在类级别没有遵守)

特点:
1.降低类的复杂度
2.提高可读性,可维护性
3.降低变更风险
4.通常情况下我们应该遵守,但不排除例外,只有代码逻辑足够简单,才允许在代码和类级别违反单一原则,在方法级别保持原则

接口隔离(segregation) 最小接口依赖规则,只与自己相关的依赖建立相关的关系,不应该依赖于它不需要的接口 都原有接口进行拆分,拆分成多个接口

依赖倒转(作用: 降低了客户和模块之间的耦合度)是实现开闭原则的重要途径之一 原则: 接口传递, 构造方法传递 setter方式传递 定义: 高层模块不应该依赖于底层模块,两者都应该依赖于抽象而不应该依赖于细节,面向接口编程,不要面向实现编程

里氏替换 (跟继承相关)里氏替换原则是实现开闭原则的重要方式之一(避免不要重写父类的方法) 定义: 所有引用基类的地方都必须能透明的使用其子类的对象 // export class LisA { // intergerSub(intA: number, intB: number): number{ // return intA - intB; // } // } // export class LisB extends LisA { // // 重写A类中的方法 // intergerSub(intA: number, intB: number): number{ // return intA + intB; // } // intergerMulti(intA: number, intB: number): number{ // return intA * intB; // } // }

  • 上面的写法会造成方法调用结果出现混淆,因为在子类的继承中重写了父类的方法,所以导致可能会造成在方法调用的时候分辨不清
  • 通过向上提取更简单的基类 让父子类共同继承该基类
  • 如果还想让原来的子类调用原来父类中的方法,那么可以使用聚合组合的方式实现,注入

开闭原则(用抽象构建框架,用实现扩展细节) 定义: 当应用的需求发生改变时,在不修改软件实体的原代码或者二进制代码的前提下,可以扩展模块的功能,能够满足新的需求

作用: (对于软件测试)
只需要对扩展代码进行测试,原有代码可以正常运行
	(提高代码的可复用性)
粒度越小,被复用的可能性就越大,原子和抽象编程
	(提高可维护性)
稳定性和延续性强,易于扩展和维护

迪米特法则【最少知道原则】(只与直接朋友联系,陌生类不要以局部变量的形式出现) 直接朋友: 两个类之间存在依赖耦合关系,一个类在另一个类中的表现形式为成员变量,方法参数和方法返回值的类称之为直接朋友 定义: 两个软件实体之间通过第三方转发调用,降低类之间的耦合度,提高模块的相对独立性 个人理解: 模块之间只需要实现自己的功能定义,如果两个实体之间需要配合使用,那么在不兼容的情况下用第三方接口完成转发

合成复用原则 原则: 在软件进行复用的情况下,首先考虑通过组合聚合的方式进行关联实现,其次才是继承关系来实现 如果要使用继承关系,则必须严格遵守里氏替换原则, 合成复用原则和里氏替换原则相辅相成,两者都是开闭原则的实现规范

继承复用和组合复用:
	组合复用: 将已有对象纳入新对象当中,并且可以增加自己额外的功能(组合复用的优点)
	1.维持了类的封装性,不会像继承复用把父类的实现都暴露给子类
	2.新旧类之间的耦合度降低
	3.复用的灵活性更高

七大原则总结: 1.开闭原则是总纲,告诉我们对外要扩展开放,对修改关闭 2.里氏替换原则则是说不要破环继承体系,通过向上抽取更简单的基类 3.依赖倒转原则则是要面向接口编程 4.单一职责则是实现类的功能要尽可能的单一 5.接口隔离原则则是在接口实现的时候要按照最小接口标准去实现 6.迪米特法则则是说降低耦合度 7.合成复用的原则则是优先考虑使用组合和聚合的方式,其次是继承

23种设计模式 创建型: 单例模式(singleton)、原型模式(Prototype)、工厂方法模式(FactoryMethod)、抽象工厂模式(AbstractFactory)、建造者模式(Constructor)

单例模式: 在软件应用当中,通常是为了节省内存资源,保证数据的一致性,对默写特定要求只能创建一个实例 优点: 1.单例模式保证内存中只有一个实例,减少内存开销 2.避免对资源的多重占用 3.可以设置全局的访问点,可以优化和共享资源的访问 缺点: 1.单例模式一般没有接口,扩展困难,如果需要扩展就需要波及原来的代码,,违背了开闭原则 2.不利于并发测试,调试过程中单例中的代码没有执行完,就不能模拟生成一个新的对象 3.单例模式的代码通常只定义一个类,如果设计不合理,很容易违背单一职责原则

推荐使用方式:
	枚举方式
	双重检查方式
	静态内部类 (jvm在进行类的装载的时候是线程安全的)

原型模式 避免使用构造方法创建多个相同或者相似的实例,使用原型模式则能解决 优点: 1.java自带原型模型基于二进制流的复制,在性能上比new一个性能更优(原型模型就指定了创建对象的种类) 2.可以使用深度克隆方式保存对象的状态 缺点: 1.需要每一个类都配置一个clone方法 2.clone方法位于类的内部,对已有的类进行改造时,就需要修改原来代码,违背了开闭原则 3.对象多层嵌用时,实现深度克隆,实现起来会比较复杂

简单工厂: 优点: 1.

缺点: 
	1.

工厂方法: 在软件应用中,做到生产和使用分离 优点: 1.只需要知道具体的工厂即可 2.典型的解耦框架,高层模块只需要知道产品的抽象类而无需知道其具体实现(满足迪米特法则,依赖倒转原则,和里氏替换原则) 缺点: 1.类的数量可能过多,复杂度增加 2.增加了系统的抽象性和理解难度 3.抽象类只能单独生产一种商品

建造者模式: 组合直接 new Object(); 聚合方式{ 构造器的方式 setter()方法 } set(Object obj)

建造者模式符合开闭原则(product,concreteConstructor,abstractConstructor, Director)
但他的适用范围要求在系统应用当中对象之间的差别不大

适配器模式: 类适配器,对象适配器,接口适配器 被适配器: src 适配器: adapter 目标: des

适配器接口: 
	对于接口中的方法并不想使用的时候全部调用,那么使用适配器接口模式建立一个抽象类默认实现接口中所有的方法(空实现),那么当我们需要在调用这个接口的时候继承这个抽象类只需要去重写我们需要调用的一个方法;
	抽象类可以使用匿名内部类的方式直接调用 	

代理模式: 优点: 1.在客户端和目标对象之间存在中介一样的关系,保护目标对象的作用 2.代理对象可以扩展目标对象的功能 3.代理模式能将客户端和目标对象分离,一定程度上降低了耦合度,增加了程序的可扩展性 缺点: 1.导致系统中的类数量增加 2.在客户端和目标对象之间增加一个代理对象,会造成请求速度的降低 3.增加了系统的复杂度 最佳实例用法就是springAOP的jdk动态代理模式 return (CustomerDao) Proxy.newProxyInstance( MyBeanFactory.class.getClassLoader(), new Class[] { CustomerDao.class }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { myAspect.myBefore(); // 前增强 Object obj = method.invoke(customerDao, args); myAspect.myAfter(); // 后增强 return obj; } });

桥接模式: 定义: 将抽象和实现分离,使它们可以独立变化。 用组合关系替代继承关系,降低了抽象和实现之间的耦合程度 优点: 1.抽象与实现分离,扩展能力强 2.符合开闭原则 3.符合合成服用原则 4.其实现细节对客户透明 缺点: 聚合关系建立在抽象层,要求开发者对于抽象化进行设计编程,能正确的识别出系统中两个独立变化的维度,增加了系统的理解和设计难度 总结: 客户端的依赖完全依赖于接口和抽象类,抽象类和接口之间则以聚合的方式相关联,具体的实现根据条件扩展

装饰器模式: 定义: 在不改变现有对象结构的情况之下,动态的给对象增加一些职责(额外的功能)的模式,对象结构性模型 优点: 1.装饰器是继承的有力补充。但比继承更加灵活,在不改变原有情况的情况之下,动态的给一个对象扩展功能,即插即用 2.通过使用装饰类及其这些装饰器的组合,可以实现不一样的效果 3.装饰器模式完全遵守开闭原则 缺点: 装饰器会增加许多的子类,过度会使得增加程序的复杂性

外观模式: 优点: 1.降低了子系统与刻划断之间的耦合度,是得子系统的变化不会影响调用它的客户类 2.对客户屏蔽了子系统的组件,减少了客户处理的对象数目,是得子系统使用起来更加容易 3.降低了大型软件系统中的编译的依赖性,简化了系统再不用平台之间的额移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象 缺点: 1.不能很好的限制客户使用子类系统,很容易带来未知风险、 2.增加新的子系统中可能需要修改外观类和客户端的源码,违背了开闭原则

享元模式: 角色: 抽象享元角色(Flyweight)、具体享元(Concrete Flyweight)角色、非享元(Unsharable Flyweight)角色、享元工厂(Flyweight Factory)角色 定义: 运用共享技术来有效的支持大量细粒度对象的复用,它通过共享的已经存在的对象来大幅度减少需要创建的对象数量,避免大量的开销,从而提高系统资源的利用率 优点: 1.相同的对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力 缺点: 1.为了使对象可以共享,需要将一些不能共享的状态外部化 2.读取享元模式的外部状态会使得运行时间稍微变长 结构与实现: 享元模式中存在两种状态: 1.内部状态:即不会随环境的改变而改变的可共享的部分 2.外部状态,之随环境而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化

组合模式: 定义: 将对象组合成树状的层次结构的模式,用来表示部分和整体的关系,使用户对单个对象和组合对象具有一致的访问性

结构及角色:
	抽象构件(Component)、树叶构件(Leaf)、树枝构件(Composite)
透明的组合模式,安全的组合模式

【行为型模式概述】

模板方法模式: 定义: 定义操作中的算法股价,而将算法的一些步骤延迟到子类进行处理,是的子类在不改变算法结构的情况下重新定义某些特定的步骤 优点: 1.封装了不变部分,扩展可变部分,他把认为是不变部分的算法封装到父类中实现,把可变部分放在扩展子类中实现 2.在父类中提取了公共的部分代码,以便于代码复用 3.部分方法是由子类实现的,因此子类可以扩展方式增加相应的功能(符合开闭原则) 缺点: 1.对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也会更加抽象 2.父类中的抽象方法有子类实现,子类执行的结果会影响父类的结果,这导致一种返乡的控制结构,他提高了代码的阅读难度

策略模式: 定义: 定义一系列的算法,并将每个算法都封装起来,是他们可以互相调换,且算法的变化不会影响使用算法的客户,把使用算法的责任和算法的实现分隔开开来,并委派给不同的对象对这些算法进行管理(算法的责任写在公共模板。算法的实现的封装成不同的包) 优点: 1.多重条件语句不易维护,使用策略模式可以避免使用多重条件语句 2.提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码 3.提供相同的行为不同的实现,客户可以根据不同的事件或空间选择不同的 4.提供了对开闭原则的支持,在不修改源码的情况下,灵活增加新的算法 5.把算法的使用放到环境类中,算法的实现移到策略类中,实现二者分离(职责和实现) 缺点: 1.客户端必须理解所有策略算法的区别,一边适合选择恰当的算法类 2.策略模式造成很多的策略类

命令模式: 解决问题: 如何将方法的请求者与方法的实现者解耦(想到要对行为进行撤销,重做,记录等操作) 定义: 将一个请求封装为一个对象,使发出请求的责任和执行请求的的责任分隔开,二者之间通过命令进行沟通,这样方便将命令对象进行存储,传递,调用,增加和管理

优点:
	1.降低了系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦
	2.增加或删除命令非常方便,采用命令模式增加与删除命令不会影响其他的类,满足开闭原则,扩展比较灵活
	3.可以实现宏命令,命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令
	4.方便undo和redo操作,命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复
缺点:
	产生大量的具体命令类,因为对每一个具体操作都需要设计一个具体的命令类,这将增加系统的复杂性
实例:
	客户端
	服务员(指令调用者)
	菜品(指令)
	厨师(命令接收者)

责任链模式: 定义: 为了避免请求发送这与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住旗下一个对象的引用而形成一条链,当请求发生时,可将请求沿着这条链传递,直导有对象处理为之

优点:
	1.降低了对象之间的耦合度。该模式市的一个对象无需知道到底是哪一个对象处理器请求以及链的结构,发送者和接收者也无需拥有对方的明确信息。
	2.增强了系统的克罗占星。可以根据需要增加新的请求和处理的类。满足开闭原则
	3.增强了给对象指派职责的灵活性,当工作流程发函俄国变化,可以动态的改变链的成员或者调动他们的次序,也可以动态的新增或删除责任
	4.简化了对象之间的连接,每个对象只需要保持一个指向器后继者的引用,不需要保持其他所有处理者的引用,避免了使用众多的if。。。else if语句
	5.责任分担,每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各个类的职责范围,符合类的单一职责原则
缺点:
	1.不能保证每个请求一定被处理,由于一个请求没有明确的接收者,所以不能保证他一定会被处理,该请求可能一直传到链的末端都得不到处理
	2.对于比较长的职责链,请求的处理可能涉及到多个处理都西昂,系统的性能将受到一定的影响
	3.职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致整个系统出错,如可能会造成循环调用

状态模式: 解决**: 当控制一个对象的状态转换的条件表达式过于复杂时,把相关”判断逻辑“提取出来,放到一系列的状态类中,这样可以把原来复杂的逻辑判断简单化

定义: 对于有状态的对象,把复杂的”判断逻辑“提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为

优点: