设计模式
定义
每一种模式都描述了一种问题的通用解决方法。这种问题在我们环境中,不停的出现。
设计模式是一种可重复使用的解决方法
构成部分
模式的名称:由少量的字组成的名称,有助于我们表达我们的设计
待解决问题:描述了何时需要运用这种模式,以及运用模式的环境(上下文)。
解决方案:描述了组成设计的元素(类和对象)、它们的关系、职责以及合作。但这种解决方案是抽象的,它不代表具体的实现。
结论:运用这种方案所带来的利和弊。主要是指它对系统的弹性、扩展性、可移植性的影响。
分类
从功能分
创建模式(Creational Patterns):对类的实例化过程的抽象。
结构模式(Structural Patterns):将类或者对象结合在一起形成更大的结构。
行为模式(Behavioral Patterns):对在不同的对象之间划分责任和算法的抽象化
从方式分
类模式:以继承的方式实现模式,静态的
对象模式:以组合的方法实现模式,动态的。
几种设计模式
Singleton单例模式
特点
是因为只有一个实例,可以减少实例频繁创建和销毁带来的资源消耗。(性能要求)
是当多个用户使用这个实例的时候,便于进行统一控制(比如打印机对象)。(功能需求)
说明
一定要由私有的构造函数,保证类实例只能通过getInstance()方法获得。
懒汉单实例的getInstance方法一定要用synchronized修饰,否则可能会产生多重实例。
尽量使用饿汉单实例
单例中的成员变量是多线程重用的,可能会产生意想不到的结果。因此尽量将单例设计为无状态对象(只提供服务,不保存状态)
理解
要确保单例模式不会因为并发问题产生多个实例,建议还是采用饿汉直接初始化。
因为单例类只会产生一个对象,所以不会因为重复创建多个实例而频繁产生GC。
在使用的时候,要注意:因为会被所有的线程所共享,如果有共享的变量,不能放开被修改,会产生并发写的问题。
因为所有的线程都会使用同一个对象,如果修改类的行为,也可以同步到所有的线程中。
适配器模式(Adapter)
实例代码
类的适配器
对象适配器
作用
系统需要使用现有的类,而这个类的接口与我们所需要的不同
我们需要对List进行排序,但是我们需要一个Sortable接口,原有的List接口不能满足要求。
应用
JDBC Driver
是对具体数据的适配器, 🌰将Oracle适配到JDBC中
JDBC-ODBC Bridge
是将Windows ODBC适配到JDBC接口中
理解
比如对List来说增加排序功能,那么增加一个适配器,去实现List和排序。
场景上来说,也可以实现从A适配到B,相当与一个转换。对A接口增加一个适配器,转换成B接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
模板方法模式(Template Method)
定义
模板方法模式是扩展功能的最基本模式之一,它是一种类的行为模式。
它是通过“继承”的方法来实现扩展
基类负责算法的轮廓和骨架
子类负责算法的具体实现
组合VS继承
基于“继承”的模板方法比“组合”更容易实现
在很多情况下,可以适当使用这种模式。
构成组件
抽象方法
protected abstract void step1();
强制子类实现该步骤。
具体方法
protected void doSomething()
子类不需要覆盖,但也可以覆盖之。
如想明确告诉子类“不要覆盖它”,最好表明:final
钩子方法
protected void setUp() {}
空的实现(缺省适配器模式)
子类可选择性的覆盖之,以便在特定的时机做些事。
理解
定义一个架子,定义了整体的执行流程,比如分为五个步骤,可以把其中某几个方法设置为抽象的,让子类去实现,去实现不同的逻辑处理。
可以减少子类的if else,只需要实现对应的抽象方法实现逻辑。
策略模式(Strategy)
定义
策略模式是扩展功能的另一种最基本的模式,它是一种“对象的行为模式”
它是通过“组合”的方法来实现扩展
使用情景
系统需要在多重算法中选择一种
重构系统时,将条件语句转换成对于策略的多态性调用
优点(对比模板方法)
将使用策略的人与策略的具体实现分离
策略对象可以自由组合
缺点
策略模式仅仅封装了“算法的具体实现”,方便添加和替换算法,但它并不关心何时使用何种算法,这个必须由客户端来决定。
策略模式和模板方法结合
理解
在运行时可以动态选择对应的策略实现,以减少if else的出现。
组合模式(Composite)
定义
是一种“对象的结构模式”
应用
文件系统
AWT控件
理解
把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
装饰器模式(Decorator)
定义
装饰器模式也被笼统的称为“包装器“(Wrapper)
适配器也被称为“包装器“,区别在于适配器是转换成另一个接口,而装饰器是保持接口不变。
包装器形成一条“链”(类似于Java IO中的调用)
是一种“对象的结构模式”
作用
在不改变对客户端的接口的前提下(对客户端透明)
扩展现有对象的功能
与模板方法、策略模式的比较
装饰器保持对象的功能不变,扩展其外围的功能
模板方法和策略模式则保持算法框架不变,而扩展其内部的实现
与继承的比较
都可以用来扩展对象的功能
但装饰器是动态的,继承是静态的
装饰器可以任意组合,但这也使装饰器更复杂,有可能会组合出荒谬的结果
应用
Java Servlet中的应用
HttpServletRequest/HttpServletRequestWrapper
HttpServletResponse/HttpServletResponseWrapper
同步化装饰器
Collections.synchronizedList(list)
取代原先的Vector、Hashtable等同步类
Java I/O库
核心:流,即数据的有序排列,将数据从源送达目的地。
流的种类
InputStream、OutputStream代表byte流(八位字节流)
Reader、Writer代表char流(Unicode字符流)
流的对称性
输入流 - 输出流
Byte - Char
理解
通过对相同基类或者接口中的抽象方法的实现,不断增强所包装的被包装的功能。
B和C都继承了A类,实现了A的doSomething方法,那么B可以对C类的doSomething方法进行增强,类似的,C类也可以对B类的doSomething进行增强。
评论