大话设计模式

Posted by 盈盈冲哥 on March 5, 2020
  • 封装

    • 每个对象都包含它能进行操作所需要的所有信息,这个特性称为封装,因此对象不必依赖其他对象来完成自己的操作。
    • 封装有很多好处,第一、良好的封装能够减少耦合,第二、类内部的实现可以自由地修改,第三、类具有清晰的对外接口。
  • 继承

    • 对象的继承代表了一种is-a的关系,如果两个对象A和B可以描述为B是A,则表明B可以继承A。
    • 继承者还可以理解为是对被继承者的特殊化,因为它除了具备背继承者的特性外,还具备自己独有的个性。
    • 如果子类继承于父类,第一、子类拥有父类非private的属性和功能,第二、子类具有自己的属性和功能,即子类可以扩展父类没有的属性和功能,第三、子类还可以以自己的方式实现父类的功能(方法重写)。
    • 构造方法不能被继承,只能被调用
    • 不用继承的话,如果要修改功能,就必须在所有复杂的方法中修改,代码越多,出错的可能就越大,而继承的优点是,继承使得所有子类公共的部分都放在了父类,使得代码得到了共享,这就避免了重复,另外,继承可使得修改或扩展继承而来的实现都较为容易。
    • 继承是有缺点的,那就是父类变,则子类不得不变。继承会破坏包装,父类实现细节暴露给子类。继承显然是一种类与类的强耦合的关系。
  • 多态

    • 多态表示不同的对象可以执行相同的动作,但要通过它们自己的实现代码来执行。
    • 注意:第一、子类以父类的身份出现,第二、子类在工作时以自己的方式来实现,第三、子类以父类的身份出现时,子类特有的属性和方法不可以使用。
    • 多态的原理是当方法被调用时,无论对象是否被转换为其父类,都只有位于对象继承链最末端的方法实现会被调用。也就是说,虚方法是按照其运行时类型而非编译时类型进行动态绑定调用的。
  • 单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。

    • 软件设计真正要做的许多内容,就是发现职责并把那些职责项目分离。
    • 如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。
  • 开放-封闭原则:软件实体(类、模块、函数等等)对于扩展是开放的,对于更改是封闭的。

    • 无论模块是多么的封闭,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。
    • 等待变化发生时立即采取行动。
    • 在我们最初编写代码时,假设变化不会发生。当发生变化时,我们就创建抽象来隔离以后发生的同类变化。
    • 面对需求,对程序的改动时通过增加新代码进行的,而不是更改现有的代码。
  • 依赖倒转原则:A. 高层模块不应该依赖低层模块。两个都应该依赖抽象。B. 抽象不应该依赖细节。细节应该依赖抽象。

    • 要针对接口编程,不要对实现编程。
    • 依赖倒转可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。
  • 里氏替换原则:子类型必须能够替换掉它们的父类型

  • 合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用类继承

    • 聚合表示一种弱的拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
    • 优先使用对象的合成/聚合讲有助于保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长位不可控制的庞然大物。
  • 简单工厂模式

  • 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

    • 类图:P71
    • Product:定义工厂方法所创建的对象的接口
    • Creator:声明工厂方法,该方法返回一个Product类型的对象
    • ConcreteProduct:具体的产品,实现了Product接口
    • ConcreteCreator:重定义工厂方法以返回一个ConcreteProduct实例
  • 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    • 类图:P150
    • AbstractFactory:抽象工厂接口,它里面应该包含所有的产品船舰的抽象方法
    • AbstractProduct:抽象产品,它们都有可能有两种不同的实现
    • ConcreteFactory1, 2:具体的工厂,创建具有特定实现的产品对象
    • ConcreteProduct1, 2:对两个抽象产品的具体分类的实现
  • 策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

    • 类图:P23
    • Context:上下文类,维护一个对Strategy的引用
    • Strategy:策略类,定义所有支持的算法的公共接口
    • ConcreteStrategy:具体策略类,封装了具体的算法或行为,继承于Strategy
  • 代理模式:为其他对象提供一种代理以控制对这个对象的访问。

    • 类图:P64
    • Subject:主体类,定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy
    • RealSubject:真实实体类
    • Proxy:代理类,保存一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这样代理就可以用来代替实体
    • 用途:代理模式其实就是在访问对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。
  • 观察者模式(发布-订阅模式):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

    • 类图:P131
    • Subject:主体类,它把所有对观察者对象的引用保存在一个聚集中,每个对象都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
    • Observer:观察者对象,抽象观察者,为所有的具体观察者定义一个接口,在得到主体的通知时更新自己。
    • ConcreteSubject:具体主体
    • ConcreteObject:具体观察者
  • 适配器模式:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

    • 类图:P172
    • Target:客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
    • Adapter:通过在内部保证一个Adaptee对象,把原接口转换成目标接口。
    • Adaptee:需要适配的类。
  • 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  • 桥接模式:将抽象部分与它的实现部分分离,使得它们都可以独立地变化。

    • 类图:P231
    • Abstract:抽象
    • Implementor:实现
    • RefinedAbstraction:被提炼的抽象
    • ConcreteImplementationA, B:具体实现
    • 实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。