十月间断的学了一些设计模式。这是个长久的课程,还没有学会怎么实际运用到项目中。
跟随着视频来学。其实理解最快的方式是看类图。
为什么学习设计模式?
为了让程序具有更好的代码重用性,可读性,可扩展性,可靠性,使程序呈现高内聚,低耦合的特性。
什么时候用到设计模式?
面向对象(oo)=> 功能模块[设计模式 + 算法(数据结构)] => 框架[ 多种设计模式 ] => 架构[ 服务器集群 ]
学习步骤
应用场景 –> 设计模式 –> 剖析原理 –> 分析实现步骤(图解,类图) –> 代码实现 –> 框架或项目源码分析的步骤讲解
设计模式的七大原则
设计模式为什么这样设计的原则。
字符流会查码表,字节流不查码表
编码:字符—>码表—>数字
解码:数字—>码表—>字符
Reader默认查询的码表是与操作系统一致的码表,操作系统是中文的,所以reader使用GBK码表
java查的是unicode的码表
1. 单一职责原则
一个类只负责一个职责。
2. 接口隔离原则
使用多个单独的接口。
3. 依赖倒转原则
其核心是面向接口编程(即抽象类)。
4. 迪米特法则(最少知道原则)
体现了封装的思想。可以适当违反。
5. 开闭原则OCP
对扩展开放,对修改关闭。
6. 里氏替换原则
oo中继承的思考。
所有引用基类的地方必须能透明的使用其子类的对象。
使用继承时尽量不要重写父类的方法。
创建一个更加基础的类。使用依赖,聚合,组合的关系。
7. 合成复用原则
尽量使用合成聚合的方式,而不是使用继承。
UML语言介绍
统一建模语言。
类图-依赖关系(Dependence)只要在类中用到了对方,他们就存在依赖关系。
类图-泛化关系(generalization),就是继承关系,是依赖关系的特例。
类图-实现关系(Implement),是依赖关系的特例
1 | public interface PersonService{ |
类图-关联关系(Association)
类与类之间的联系,是依赖关系的特例。有单向和双向关系。
类图-聚合关系(Aggregation) 整体与部分的关系,整体与部分可以分开。比如Person和IDCard。聚合式关联关系的特例。
类图-组合关系(Composition)也是整体与部分的关系,但是整体与部分不可以分开。例如Person和head。同生共死的关系。
1 | public class Person{ |
创建型模式
单例模式
主要步骤:
1) 构造器私有化 (防止 new )
2) 类的内部创建对象
3) 向外暴露一个静态的公共方法
饿汉式
1 | class Singleton{ |
优缺点:写法简单,在类装载的时候完成实例化,避免了线程同步问题,没有达到懒加载的效果。
可用,但会造成内存的浪费。
双重检查
1 | class Singleton{ |
Double-Check是多线程开发中常使用的。线程安全,延迟加载,效率较高。
静态内部类
1 | class Singleton{ |
静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在需要实例化时,调用 getInstance 方法,才会装载 SingletonInstance 类,从而完成 Singleton 的实例化。避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。推荐使用。
枚举法
1 | enum Singleton{ |
借助 JDK1.5 中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。这种方式是 Effective Java 作者 Josh Bloch 提倡的方式.推荐使用
简单工厂模式
1 | ... |
服务器修改了具体产品的类名后,客户端不知道。
工厂的实现不易于扩展,违反了ocp原则,故引入了工厂方法模式。
工厂方法模式
1 | interface food{ |
工厂的名字是视为接口的,是趋向稳定的。
但是当种类很多时,会造成类爆炸式增长,于是引入抽象工厂。
抽象工厂
1 | interface Factory{ |
无论有多少产品等级,工厂就一类。
冰箱电视洗衣机视为产品等级,工厂厂家海尔海信华为系列产品视为产品簇。虽然新增一个工厂很便捷,但抽象工厂扩展产品等级需要所有的工厂都修改,用Spring框架解决。
抽象工厂中可以生产多个产品,这多个产品之间必有内在联系。同一个工厂中的产品都属于一个产品簇。
原型模式
原型模式用于创建重复的对象,同时又能保证性能。
当直接创建对象的代价比较大时,可以采用这种方式。
源码应用有Spring
1 | public class Sheep implements Cloneable{ |
Java中的Object类是所有类的根类,Object类提供了一个clone()的方法。需要实现clone的java类必须实现一个接口Cloneable,该接口表示该类能复制且有复制的能力。
上例的clone实现使用了默认的clone(),是浅拷贝,要实现深拷贝可以采用重写clone函数或者序列化。
c++可以用拷贝构造函数
1 | class ISplitter{ |
建造者模式
使用多个简单的对象一步一步构建成一个复杂的对象。
源码应用有StringBuilder
建造产品的过程的产品解耦合?
与工厂模式的区别:
1 | //Product |
结构型模式
适配器模式
Adapter, 对应源码中的应用有Dispatcher handler
作为两个不兼容的接口之间的桥梁。
举例为电压转换
桥接模式
Bridge,源码应用有JDBC:driver
将抽象化和实现解耦
手机品牌问题
组合模式
Comoposite, 源码应用有HashMap
根据树形结构来组合对象
院校展示问题
装饰模式
Decorator, 源码应用有IO
向现有的对象中添加新的功能
咖啡加料问题
外观模式
Facade, 源码应用有Mybatis
隐藏系统复杂性,向客户端提供一个客户端可以访问的接口
影院仪器管理问题
享元模式
Flyweight, 源码应用有数据库连接池 Integer
重用现有的同类对象
棋盘问题
代理模式
Proxy, 源码应用有AOP
一个类代表另一个类的功能
行为型模式
责任链模式
源码应用:SpringMVC中的ServletFilter, Spring中的SpringInterceptor AOP也通过这一模式来顺序执行每一个通知