多态+依赖抽象(组合抽象类)+面向抽象(即面向接口编程而不是针对实现编程,这样就能减少对具体类之间的依赖)
解耦:通过在中间多加点东西使得不变的代码和可能改变的代码分开在不同的类中,即封装变化
1.策略模式:
定义:定义了算法族,将变化的部分封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
特点:组合+委托(使用算法的客户 将行为的实现 委托 给 算法对象,有一个的关系);可以运行时改变算法的实现(对象)
2.观察者模式:
定义:定义了对象之间一对多的依赖关系,当主题对象改变时,观察者对象都能收到通知
特点:主题对象+观察者对象;一对多关系(被观察者内部一般有个list用来保存多个观察者的引用,同时会有添加观察者到list的方法,比如register/add方法);松耦合(主题对象不需要知道观察者对象具体实现的细节,只要知道主题状态改变时,需要调用观察者们都实现的哪个方法来通知他们即可)
数据的通知方式:推和拉俩种;
观察者注册方式:注册观察者删除观察者的权利可以交给观察者自身,也可以只由主题对象来控制
3.装饰者模式
定义:可以动态(非编译)的将功能附加在对象上
特点:装饰者+被装饰者;装饰者和被装饰者对象有相同的超类型(一般的所有的装饰者可能也有共同的父类(也是共同超类的子类));组合关系(装饰者对象中有一个被装饰者,通过委托增加新功能)
4.工厂模式:
1)简单工厂:单独的定义了一个类用来创建对象,适用于重复根据条件创建具体对象的场景下(参数化工厂方法)
2)工厂方法模式:抽象超类定义了一个创建对象的接口,但是由子类实现该接口决定如何创建对象,工厂方法让类的创建推迟到了子类,而类的使用已经在超类中实现了(工厂方法模式帮助我们将对象的实现从使用中解耦)
3)抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族(子类不同的实现),而不需要明确指定具体的类。(可以看成是多个工厂方法的集合)
抽象工厂适用于 同样的工厂创建出的类可能由不同的实现情况下使用。
工厂方法和抽象工厂的区别:工厂方法用的是继承(子类重写工厂方法实现创建具体对象);抽象方法用的是组合(需要将工厂子类实例传递给针对抽象类型所写的代码中使用)
5.单件模式:
定义:确保一个类只有一个实例,并提供一个全局访问点
特别的需要注意的是,延迟实例化的多线程问题。而急切创建实例的方式就没有多线程问题。解决延迟实例化多线程问题可以用 急切实例化代替;同步方法和双重检查加锁
6.命令模式:
定义:可以将请求的发出者(对象)和实际请求的执行者(对象)解耦
特点:请求发出对象+命令对象+请求实际执行对象;(这个模式看类图能更快的理解)
7.适配器模式和外观模式:
适配器模式:
定义:将一种接口转换为另一种目标接口
特点:目标接口(由适配器来实现)+ 适配器对象 + 待适配对象
外观模式:
定义:外观模式是为了简化接口(适配器模式是为了改变接口)
适配器模式和装饰者模式的区别:
适配器模式:改变接口;装饰者模式:不改变接口。适配器模式和待适配对象之间只有组合的关系,而装饰者一般装饰者和被装饰者有共同的超类
8.模板方法模式:
定义:在一个方法中(一般是抽象父类的一个方法)定义了一个算法的骨架,而讲一些步骤延迟到子类中。模板方法使得子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
特点:模板方法是利用继承实现的而不是组合
钩子方法:是一种声明在抽象类中的方法,但只有空的或者默认的实现,子类可以根据需要判断是否重写该方法
模板方法和策略模式的区别:
1)模板方法使用继承,策论模式使用组合
2)模板方法只是规定了算法流程,不负责实现(也可以部分实现或者特殊的全部实现),而策论模式组合的类实现了整个算法
3)模板方法使用继承,策论模式使用组合(运行时可以改变算法即依赖对象的实现)
9.迭代器和组合模式
迭代器模式:
定义:提供了一种顺序访问一个集合对象中的各个元素,而又不暴露其内部的表示
特点:可以让类实现单一责任即某个类(创建迭代器的类)只负责管理集合而将遍历集合的责任交给迭代器实现
注意:迭代器模式是在调用next()方法的时候将指针后移的,hasNext()方法只是做判断
组合模式:
定义:允许你将对象组合成树形结构来表现整体/部分的层次结构。组合能够让客户以一致的方式处理个别对象以及对象组合
特点:特点:能够使用一致的方式处理对象和对象的组合(意味着对象和对象的组合都要实现相同的接口里所有方法,即使对象和对象的组合之间可能存在行为上的不一致。)。当然也可以针对对象和对象的组合实现不同的方法,这样就是更加安全版的组合模式,但是这样带来了不能统一处理对象的问题,操作前需要先检查对象的类型。这个问题需要设计的时候权衡
10.状态模式
定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类
适用场景:类内部有一系列状态,需要通过很多if..else..来判断状态进而执行对应的方法时。
特点:将每个状态封装成一个类,并将该状态下能够发生的行为一并封装进类中
状态模式和策略模式的区别:
相同点:状态和策略模式的类图是一样的,都是通过组合+委托的方式实现,都能动态改变类的行为
不同点:虽然类图一样,但是出发点不一样。状态模式 委托的当前状态会在 状态对象集合中游走,从而导致行为不一样,但是客户对于状态了解不多甚至是不知道的;而策略模式客户通常主动指定所要组合的策略对象是哪一个
11.代理模式
定义:为另一个对象提供一个替身或占位符以控制这个对象的访问
动态代理:和一般代理不同的地方是,代理对象是在运行时由java产生,而不是由我们自己写代码实现。动态代理执行的过程是 客户调用代理对象的方法,代理对象再调用InvocationHandler的invoke方法(代理对象通过Proxy类创建的时候需要传递InvocationHandler对象),从而委托(说明InvocationHandler对象中依赖了真正的对象)给真正的对象执行。得到代理对象可以通过工厂方法来实现比较好。
代理模式和装饰者模式的区别:
虽然实现的方式都是一样(多态,组合委托)。但是侧重点不同:装饰者为对象增加行为(可能会为多次包装对象,而代理模式一般不会多次代理对象),代理模式是控制访问。
代理模式和适配器的区别:
适配器会改变对象的接口,而代理模式则实现相同的接口
--------------------------------------------
“许多人被创建型,结构型,行为型类目搞得一头雾水。请记住,怎么分类并不重要,重要的是了解这些模式和它们之间的关系。只要类目有帮助,我们就用它,反之就不用”
模式会带来复杂性,非必须的情况下不适用模式。应该总是使用最简单的解决方案完成工作