设计模式七大原则
开闭原则:软件实体应当对扩展开放,对修改关闭,这就是开闭原则的经典定义。
里氏替换原则:通俗来讲就是,子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
依赖倒置原则:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象(接口或者抽象类)不应该依赖细节(实现类),细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。
单一职责原则:单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。通俗地说,一个类负责一项职责。
接口隔离原则:要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
迪米特法则:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
只与直接朋友通信。迪米特法则中的“直接朋友”是指:成员变量、方法参数、方法返回值中的类为直接朋友,而出现在局部变量中的类不是直接朋友。也就是说,陌生类最好不要以局部变量的形式出现在类的内部。
合成复用原则:类复用时,要尽量先使用组合或者聚合等关联关系,其次才考虑使用继承关系。
类图之间的关系
继承、实现、依赖、关联、聚合、组合
组合与聚合都有整体与部分的关系,区别是:
聚合关系的整体与部分可以分割,
组合关系的整体与部分不可分割。
创建型
创建型模式的主要关注点是“怎样创建对象?”
单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
工厂方法(FactoryMethod)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
简单工厂模式
简单工厂: 直接通过一个Factory类创建多个实体类的构造方式。
工厂方法模式
工厂方法: 一个抽象产品类,可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。每个具体工厂类只能创建一个具体产品类的实例
抽象工厂模式
抽象工厂:每个抽象产品类可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。每个具体工厂类可以创建多个具体产品类的实例。
原型模式
原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
java创建对象的四种方式:
new、反射、序列化、clone
建造者模式
建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。
结构型模式
描述如何将类或对象按某种布局组成更大的结构。
装饰(Decorator)器模式:动态地给对象增加一些职责,即增加其额外的功能。
代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
装饰器模式
装饰者模式的应用场景:
1、 想透明并且动态地给对象增加新的职责的时候。
2、 给对象增加的职责,在未来存在增加或减少可能。
3、 用继承扩展功能不太现实的情况下,应该考虑用组合的方式。
装饰者模式的优点:
1、 通过组合而非继承的方式,实现了动态扩展对象的功能的能力。
2、 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
3、 充分利用了继承和组合的长处和短处,在灵活性和扩展性之间找到完美的平衡点。
4、 装饰者和被装饰者之间虽然都是同一类型,但是它们彼此是完全独立并可以各自独立任意改变的。
5、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
装饰者模式的缺点:
1、 装饰链不能过长,否则会影响效率。
2、 因为所有对象都是Component,所以如果Component内部结构发生改变,则不可避免地影响所有子类(装饰者和被装饰者),也就是说,通过继承建立的关系总是脆弱地,如果基类改变,势必影响对象的内部,而通过组合(Decoator HAS A Component)建立的关系只会影响被装饰对象的外部特征。
3、只在必要的时候使用装饰者模式,否则会提高程序的复杂性,增加系统维护难度。
代理模式
静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成
适配器模式
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
行为型模式
用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
模板(Template Method)模式:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
观察者模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
模板方法模式
策略模式类图
对于Strategy模式来说,主要有这些应用场景:
1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。(例如FlyBehavior和QuackBehavior)
2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。(例如FlyBehavior和QuackBehavior的具体实现可任意变化或扩充)
3、 对客户(Duck)隐藏具体策略(算法)的实现细节,彼此完全独立。
对于Strategy模式来说,主要有如下优点:
1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
对于Strategy模式来说,主要有如下缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
观察者模式