-------->组合/聚合复用原则
----->设计画笔
----->毛笔类+颜色类
----->12 + 3
----->添加一个颜色只需要添加一个子类
---->添加一个型号只需要添加一个子类
---->毛笔类负责了型号的变化,颜色类负责了颜色的变化
------>组合/聚合是has-a关系是加法关系
---->N+M
---------->接口隔离原则
------>提炼接口隔离变化、并统一行为
------>JDBC设计中
----->由于数据库是变化的
----->Sun公司提炼了数据库操作的接口
----->具体的实现交给了数据库厂商
------>避免肥胖接口的问题
------>适配器模式是接口隔离最好的体现
----->对象适配器、类适配器
----->类适配器一般采用继承的方法,对象的适配器采用组合聚合的方法
----->用来转换类型(语法上比较简单)
----->实际应用中,要转换的那个类型往往是不存在的,需要通过变化进行接口的提炼。
----->缺省适配器
----->解决肥胖接口问题的。
-------->依赖倒置原则
------>依赖于抽象而不依赖于具体
------>协作开发
----->依赖有变化的时候
------>稳定不变且事先存在的依赖可以依赖具体
-------->里氏替换原则
-------->任何父类的引用都可以用子类的实例。
-------->子类不能比父类有更多的约束。
-------->is-a不是数学上的而是行为上的。
------->迪米特法则
------>不要根陌生人说话,只根朋友交谈。
------>外观模式、调停者(中介者)模式都是该原则的体现。
1.创建型的模式
------->目标都是创建对象,使得使用者和创建者分离
------->使用者拿到对象用即可,不用关心对象的创建
------->也就实现了控制反转
------->简单工厂设计模式(并不在23种设计模式之内)
------>一般来说创建单个具体类的实例对象
------>直接通过静态的方法返回要创建的对象
------>如果产品有一个抽象,有多个具体子类,动态扩展更多的子类
----->原始的简单工厂就是通过传递参数
---->根据参数判断创建对象
---->如果动态添加新的产品,那么工厂就需要修改原有的逻辑判断。
---->一般来说使用工厂方法设计模式来解决。
---->在Java语言中可以具体解耦来解决
---->配置文件+反射解耦即可
--------->工厂方法设计模式
------>一个抽象产品,多个具体产品,可以动态扩展子类。
------>一个抽象工厂类,添加一个具体产品,就添加一个具体工厂
------>使用者需要依赖与具体的工厂
----->可以把具体的工厂配置到配置文件中通过反射解决
----->还不如直接回到简单工厂+配置文件+反射
------->抽象工厂设计模式
------>一组抽象产品,称为一个家族(至少两个)
------>动态添加对象的家族
------>一个抽象工厂
----->动态添加一个家族,动态创建一个具体工厂
------>使用者依赖与具体的工厂,而不需要知道具体的类
------->单例模式
------->对象有且只有一个。
------->单例模式是绕不开反射
------->整个应用对象有一个即可这种情况
------->如果是为了加载资源,只加载一次,
----->对象只创建一个,在构造函数中加载。
----->这种情况可以通过静态块代替。
-------->扩展
------>对象数目已知且固定
------>枚举
------>一样可以通过枚举的方式来写单例模式。
------->线程范围内单例模式
----->不是类本身是单例的。
----->ThreadLocal
----->数据库的连接对象就需要同一个线程同一个对象
-------->原型模式(对象的克隆)
------->浅拷贝
----->jdk中的Object类直接支持的,类实现CloneAble接口
------->深拷贝
------>需要自己书写方法
------>通过序列化技术来实现
-------->构建者模式
------->创建一个对象的过程比较复杂
------->这个对象有多个小对象组成
------->而每个小对象又是变化的
------->如麦当劳儿童套餐
----->都是由一个主食、辅食、饮料、玩具组成
----->A套餐和B套餐每个小对象可能是不一样的
------->抽象的构建者角色
------->具体的构建者角色
2.结构型模式
-------->适配器模式
-------->装饰器模式
------->在不改变原有类代码的基础上,给类动态添加新的功能。
------->new E(new D(new C(new B(new A()))))
------>B,C,D,E... ...都可以交换位置
------>假设A类有抽象的父类叫X
------>B,C,D,E有父类Y,那么Y应该如何声明,上面的表达式才能够成立。
---->class Y extends X{
private X x;
public Y(X x){
this.x = x;
}
}
----->Y称为抽象的装饰器类
----->具体的装饰器只要继承Y即可。
-------->类型不发生变化
-------->java的IO中的各种字节流都是通过原始的节流包装而来,使用了装饰器模式
-------->适配器模式类型是发生变化的。
----->java的Io中 字符流是通过字节流适配而来(对象适配器)。
------->装饰器模式和适配器模式经常组合在一起使用。
-------->代理模式(实现方法的拦截,AOP的核心)
------>静态代理模式
------>创建一个类和目标类实现同一个接口
------>一个一个方法去拦截
------>动态代理模式
------>jdk支持的动态代理(必须面向接口编程)
----->java.lang.reflect.InvocationHandler
----->java.lang.reflect.Proxy
----->方法全部拦截
------>cglib支持的动态代理(不需要面向接口编程)
------>下载cglib jar包
------>创建类实现cglib提供的net.sf.cglib.proxy.MethodInterceptor接口
------>重写intercept方法
------>目标对象任何方法的调用都会被该方法拦截。
------>通过该类
---->net.sf.cglib.proxy.Enhancer创建代理对象
------->理解AOP的设计思想。
-------->享元模式
------->有些对象在应用中可能反复 做创建和销毁的工作
------->这种情况下可以把对象创建出来并缓存起来,下次直接使用即可。
-------->java中的字符串操作、封装类默认都有享元模式
-------->没有固定的语法套路
----->需要有一个类完成(该类角色称为享元工厂角色)
----->先从缓存中取,如果没有就创建一个放入缓存中
----->注意多线程访问的问题(用读写锁或者线程安全的Map集合)
----->缓存的对象可以使用软引用
-------->桥接模式
------>组合/聚合复用原则的体现
------>毛笔+颜色 案例
------>飞机+制造商 案例
-------->组合模式(使用较少)
------>把一个聚集和单个对象当做同一个类型来处理
------>文件夹和文件、树枝和树叶
-------->外观模式(使用较少)
------->把复杂的操作进行包装,提供更简洁的API操作。
------->是迪米特法则的一个体现。
3.行为型的设计模式
--------->命令模式
------->解耦请求的发送者和接受者。
------->把请求包装成命令
------->四个角色
----->请求的发送者角色
----->请求的接受者角色
----->抽象命令角色
----->具体的命令角色
--------->策略模式
------>实现某个功能有多条途径
------>每条途径对应一个算法
------>把算法进行抽象
------>每条途径就是具体的子类
------>在使用的地方使用父类的引用
------>将来引用具体的子类实例,就可以调用具体的子类算法
------>可以通过配置文件解耦
--------->状态模式(使用较少)
------>对象的状态发生了变化,行为就发生了变化。
------>状态的切换过程
------>把状态的行为进行抽象
------>每种状态的行为就是一个具体的子类实例
------>维持对抽象状态的引用
------>状态切换的代码只能违背开闭原则
--------->观察者模式
------>一个对象(目标对象)的状态发生了改变,
----->与其相关的对象(观察者)
----->都各自产生各自的行为
------->目标对象
------>应该有容器(可以添加、移除、遍历观察者)
------->观察者
------>需要有统一的抽象。
--------->模板方法设计模式
------>定义了一个算法的骨架(步骤)
---->步骤顺序定死了
------>每一步的具体实现延迟到子类当中
--------->迭代器模式
------>提供聚集就需要提供遍历和查找的方式
------>并且不暴露聚集的具体实现
------>我们使用聚集的时候都是用的java提供的集合
----->它们已经实现了迭代器模式
----->我们一般不用自己写。
----->设计画笔
----->毛笔类+颜色类
----->12 + 3
----->添加一个颜色只需要添加一个子类
---->添加一个型号只需要添加一个子类
---->毛笔类负责了型号的变化,颜色类负责了颜色的变化
------>组合/聚合是has-a关系是加法关系
---->N+M
---------->接口隔离原则
------>提炼接口隔离变化、并统一行为
------>JDBC设计中
----->由于数据库是变化的
----->Sun公司提炼了数据库操作的接口
----->具体的实现交给了数据库厂商
------>避免肥胖接口的问题
------>适配器模式是接口隔离最好的体现
----->对象适配器、类适配器
----->类适配器一般采用继承的方法,对象的适配器采用组合聚合的方法
----->用来转换类型(语法上比较简单)
----->实际应用中,要转换的那个类型往往是不存在的,需要通过变化进行接口的提炼。
----->缺省适配器
----->解决肥胖接口问题的。
-------->依赖倒置原则
------>依赖于抽象而不依赖于具体
------>协作开发
----->依赖有变化的时候
------>稳定不变且事先存在的依赖可以依赖具体
-------->里氏替换原则
-------->任何父类的引用都可以用子类的实例。
-------->子类不能比父类有更多的约束。
-------->is-a不是数学上的而是行为上的。
------->迪米特法则
------>不要根陌生人说话,只根朋友交谈。
------>外观模式、调停者(中介者)模式都是该原则的体现。
1.创建型的模式
------->目标都是创建对象,使得使用者和创建者分离
------->使用者拿到对象用即可,不用关心对象的创建
------->也就实现了控制反转
------->简单工厂设计模式(并不在23种设计模式之内)
------>一般来说创建单个具体类的实例对象
------>直接通过静态的方法返回要创建的对象
------>如果产品有一个抽象,有多个具体子类,动态扩展更多的子类
----->原始的简单工厂就是通过传递参数
---->根据参数判断创建对象
---->如果动态添加新的产品,那么工厂就需要修改原有的逻辑判断。
---->一般来说使用工厂方法设计模式来解决。
---->在Java语言中可以具体解耦来解决
---->配置文件+反射解耦即可
--------->工厂方法设计模式
------>一个抽象产品,多个具体产品,可以动态扩展子类。
------>一个抽象工厂类,添加一个具体产品,就添加一个具体工厂
------>使用者需要依赖与具体的工厂
----->可以把具体的工厂配置到配置文件中通过反射解决
----->还不如直接回到简单工厂+配置文件+反射
------->抽象工厂设计模式
------>一组抽象产品,称为一个家族(至少两个)
------>动态添加对象的家族
------>一个抽象工厂
----->动态添加一个家族,动态创建一个具体工厂
------>使用者依赖与具体的工厂,而不需要知道具体的类
------->单例模式
------->对象有且只有一个。
------->单例模式是绕不开反射
------->整个应用对象有一个即可这种情况
------->如果是为了加载资源,只加载一次,
----->对象只创建一个,在构造函数中加载。
----->这种情况可以通过静态块代替。
-------->扩展
------>对象数目已知且固定
------>枚举
------>一样可以通过枚举的方式来写单例模式。
------->线程范围内单例模式
----->不是类本身是单例的。
----->ThreadLocal
----->数据库的连接对象就需要同一个线程同一个对象
-------->原型模式(对象的克隆)
------->浅拷贝
----->jdk中的Object类直接支持的,类实现CloneAble接口
------->深拷贝
------>需要自己书写方法
------>通过序列化技术来实现
-------->构建者模式
------->创建一个对象的过程比较复杂
------->这个对象有多个小对象组成
------->而每个小对象又是变化的
------->如麦当劳儿童套餐
----->都是由一个主食、辅食、饮料、玩具组成
----->A套餐和B套餐每个小对象可能是不一样的
------->抽象的构建者角色
------->具体的构建者角色
2.结构型模式
-------->适配器模式
-------->装饰器模式
------->在不改变原有类代码的基础上,给类动态添加新的功能。
------->new E(new D(new C(new B(new A()))))
------>B,C,D,E... ...都可以交换位置
------>假设A类有抽象的父类叫X
------>B,C,D,E有父类Y,那么Y应该如何声明,上面的表达式才能够成立。
---->class Y extends X{
private X x;
public Y(X x){
this.x = x;
}
}
----->Y称为抽象的装饰器类
----->具体的装饰器只要继承Y即可。
-------->类型不发生变化
-------->java的IO中的各种字节流都是通过原始的节流包装而来,使用了装饰器模式
-------->适配器模式类型是发生变化的。
----->java的Io中 字符流是通过字节流适配而来(对象适配器)。
------->装饰器模式和适配器模式经常组合在一起使用。
-------->代理模式(实现方法的拦截,AOP的核心)
------>静态代理模式
------>创建一个类和目标类实现同一个接口
------>一个一个方法去拦截
------>动态代理模式
------>jdk支持的动态代理(必须面向接口编程)
----->java.lang.reflect.InvocationHandler
----->java.lang.reflect.Proxy
----->方法全部拦截
------>cglib支持的动态代理(不需要面向接口编程)
------>下载cglib jar包
------>创建类实现cglib提供的net.sf.cglib.proxy.MethodInterceptor接口
------>重写intercept方法
------>目标对象任何方法的调用都会被该方法拦截。
------>通过该类
---->net.sf.cglib.proxy.Enhancer创建代理对象
------->理解AOP的设计思想。
-------->享元模式
------->有些对象在应用中可能反复 做创建和销毁的工作
------->这种情况下可以把对象创建出来并缓存起来,下次直接使用即可。
-------->java中的字符串操作、封装类默认都有享元模式
-------->没有固定的语法套路
----->需要有一个类完成(该类角色称为享元工厂角色)
----->先从缓存中取,如果没有就创建一个放入缓存中
----->注意多线程访问的问题(用读写锁或者线程安全的Map集合)
----->缓存的对象可以使用软引用
-------->桥接模式
------>组合/聚合复用原则的体现
------>毛笔+颜色 案例
------>飞机+制造商 案例
-------->组合模式(使用较少)
------>把一个聚集和单个对象当做同一个类型来处理
------>文件夹和文件、树枝和树叶
-------->外观模式(使用较少)
------->把复杂的操作进行包装,提供更简洁的API操作。
------->是迪米特法则的一个体现。
3.行为型的设计模式
--------->命令模式
------->解耦请求的发送者和接受者。
------->把请求包装成命令
------->四个角色
----->请求的发送者角色
----->请求的接受者角色
----->抽象命令角色
----->具体的命令角色
--------->策略模式
------>实现某个功能有多条途径
------>每条途径对应一个算法
------>把算法进行抽象
------>每条途径就是具体的子类
------>在使用的地方使用父类的引用
------>将来引用具体的子类实例,就可以调用具体的子类算法
------>可以通过配置文件解耦
--------->状态模式(使用较少)
------>对象的状态发生了变化,行为就发生了变化。
------>状态的切换过程
------>把状态的行为进行抽象
------>每种状态的行为就是一个具体的子类实例
------>维持对抽象状态的引用
------>状态切换的代码只能违背开闭原则
--------->观察者模式
------>一个对象(目标对象)的状态发生了改变,
----->与其相关的对象(观察者)
----->都各自产生各自的行为
------->目标对象
------>应该有容器(可以添加、移除、遍历观察者)
------->观察者
------>需要有统一的抽象。
--------->模板方法设计模式
------>定义了一个算法的骨架(步骤)
---->步骤顺序定死了
------>每一步的具体实现延迟到子类当中
--------->迭代器模式
------>提供聚集就需要提供遍历和查找的方式
------>并且不暴露聚集的具体实现
------>我们使用聚集的时候都是用的java提供的集合
----->它们已经实现了迭代器模式
----->我们一般不用自己写。