设计模式学习

看云 · 设计模式之禅

六大原则

单一职责原则 (Single Responsibility Principle) (简称SRP)

里氏替换原则 (Liskov Substitution Principle)(简称LSP)

面向对象的继承

  • 优点
    • 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
    • 提高代码的重用性;
    • 提高代码的可扩展性
    • 提高产品或项目的开放性。
  • 缺点
    • 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法
    • 降低代码的灵活性。子类必须拥有父类的属性和方法
    • 增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改。

使用继承时,怎么才能让“利”的因素发挥最大的作用,同时减少“弊”带来的麻烦呢?解决方案是引入里氏替换原则

  • 定义: 第一种

If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型

  • 定义: 第二种

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

所有引用基类的地方必须能透明地使用其子类的对象

1
通俗定义: 只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常, 但是,反过来就不行了,有子类出现的地方,父类未必就能适应

里氏替换原则 定义了良好的继承规范

  • 子类必须完全实现父类的方法
  • 子类可以有自己的个性
  • 覆盖或实现父类的方法时输入参数可以被放大
  • 覆写或实现父类的方法时输出结果可以被缩小

依赖倒置原则 (Dependence Inversion Principle)(简称DIP)

定义

  • 高层模块不应该依赖低层模块,两者都应该依赖其抽象
  • 抽象不应该依赖细节
  • 细节应该依赖抽象
1
2
3
4
底层模块: 不可分割原子逻辑
高层模块: 原子逻辑的再组装
抽象: 接口, 不能直接被实例化
细节: 实现类, 实现接口产生的类,可以直接实例化

更精简的定义: 面向接口编程 - OOD(Object-Oriented Design,面向对象设计)的精髓之一

优点

减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性

接口隔离原则

接口尽量细化,同时接口中的方法尽量少

迪米特法则 (Law of Demeter,LoD)

也称 最少知识原则(Least Knowledge Principle,LKP)

  • 核心观念: 类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以提高

开闭原则

应尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来完成变化, 它是为软件实体的未来事件而制定的对现行开发设计进行约束的一个原则

23种设计模式

单例模式

  • 定义
1
2
一个类只能生成一个对象, 自行实例化并向整个系统提供这个实例 
通过定义一个私有访问权限的构造函数,避免被其他类new出来一个对象
  • 应用
1
2
3
4
5
6
7
8
9
10
11
12
内存中只有一个实例
优点:
减少了内存开支
减少了系统的性能开销
避免对资源的多重占用
在系统设置全局的访问点,优化和共享资源访问

如: 读取配置,一个写文件动作

缺点:
扩展困难
对测试不利,单例模式没有完成不能测试

工厂方法模式

  • 定义
1
2
Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.
(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
  • 优点
1
2
3
良好封装性: 一个对象创建是有条件约束的,如一个调用者需要一个具体的产品对象,只要知道这个产品的类名,降低模块间的耦合
扩展优秀: 在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成“拥抱变化”

抽象工厂模式