写点什么

设计模式

用户头像
Jeff
关注
发布于: 2020 年 06 月 29 日

定义

  • 每一种模式都描述了一种问题的通用解决方法。这种问题在我们环境中,不停的出现。

  • 设计模式是一种可重复使用的解决方法

构成部分

  1. 模式的名称:由少量的字组成的名称,有助于我们表达我们的设计

  2. 待解决问题:描述了何时需要运用这种模式,以及运用模式的环境(上下文)。

  3. 解决方案:描述了组成设计的元素(类和对象)、它们的关系、职责以及合作。但这种解决方案是抽象的,它不代表具体的实现。

  4. 结论:运用这种方案所带来的利和弊。主要是指它对系统的弹性、扩展性、可移植性的影响。

分类

从功能分

  1. 创建模式(Creational Patterns):对类的实例化过程的抽象。

  2. 结构模式(Structural Patterns):将类或者对象结合在一起形成更大的结构。

  3. 行为模式(Behavioral Patterns):对在不同的对象之间划分责任和算法的抽象化

从方式分

  1. 类模式:以继承的方式实现模式,静态的

  2. 对象模式:以组合的方法实现模式,动态的。

几种设计模式

  1. Singleton单例模式

  • 特点

  • 是因为只有一个实例,可以减少实例频繁创建和销毁带来的资源消耗。(性能要求)

  • 是当多个用户使用这个实例的时候,便于进行统一控制(比如打印机对象)。(功能需求)

  • 说明

  • 一定要由私有的构造函数,保证类实例只能通过getInstance()方法获得。

  • 懒汉单实例的getInstance方法一定要用synchronized修饰,否则可能会产生多重实例。

  • 尽量使用饿汉单实例

  • 单例中的成员变量是多线程重用的,可能会产生意想不到的结果。因此尽量将单例设计为无状态对象(只提供服务,不保存状态)

  • 理解

  • 要确保单例模式不会因为并发问题产生多个实例,建议还是采用饿汉直接初始化。

  • 因为单例类只会产生一个对象,所以不会因为重复创建多个实例而频繁产生GC。

  • 在使用的时候,要注意:因为会被所有的线程所共享,如果有共享的变量,不能放开被修改,会产生并发写的问题。

  • 因为所有的线程都会使用同一个对象,如果修改类的行为,也可以同步到所有的线程中。

  1. 适配器模式(Adapter)

  • 实例代码

  • 类的适配器

public class SortableList<T> extends ArrayList<T> implements NewSortable<T> {
public T getElement(int i) {
return get(i);
}
public void setElement(int i, T o) {
set(i, o)
}
}
public interface NewSortable<T> {
int size();
T getElement(int i);
void setElement(int i, T o);
}
  • 对象适配器

public class ListSortable<T> implements Sortable<T> {
private final List<T> list;
public ListSortable(List<T> list) {
this.list = list;
}
public int size() {
return list.size();
}
public T get(int i) {
return list.get(i);
}
public void set(int i, T o) {
list.set(i, o);
}
}



  • 作用

  • 系统需要使用现有的类,而这个类的接口与我们所需要的不同

  • 我们需要对List进行排序,但是我们需要一个Sortable接口,原有的List接口不能满足要求。

  • 应用

  • JDBC Driver

  • 是对具体数据的适配器, 🌰将Oracle适配到JDBC中

  • JDBC-ODBC Bridge

  • 是将Windows ODBC适配到JDBC接口中

  • 理解

  • 比如对List来说增加排序功能,那么增加一个适配器,去实现List和排序。

  • 场景上来说,也可以实现从A适配到B,相当与一个转换。对A接口增加一个适配器,转换成B接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

  1. 模板方法模式(Template Method)

  • 定义

  • 模板方法模式是扩展功能的最基本模式之一,它是一种类的行为模式。

  • 它是通过“继承”的方法来实现扩展

  • 基类负责算法的轮廓和骨架

  • 子类负责算法的具体实现

  • 组合VS继承

  • 基于“继承”的模板方法比“组合”更容易实现

  • 在很多情况下,可以适当使用这种模式。

  • 构成组件

  • 抽象方法

  • protected abstract void step1();

  • 强制子类实现该步骤。

  • 具体方法

  • protected void doSomething()

  • 子类不需要覆盖,但也可以覆盖之。

  • 如想明确告诉子类“不要覆盖它”,最好表明:final

  • 钩子方法

  • protected void setUp() {}

  • 空的实现(缺省适配器模式)

  • 子类可选择性的覆盖之,以便在特定的时机做些事。

  • 理解

  • 定义一个架子,定义了整体的执行流程,比如分为五个步骤,可以把其中某几个方法设置为抽象的,让子类去实现,去实现不同的逻辑处理。

  • 可以减少子类的if else,只需要实现对应的抽象方法实现逻辑。

  1. 策略模式(Strategy)

  • 定义

  • 策略模式是扩展功能的另一种最基本的模式,它是一种“对象的行为模式”

  • 它是通过“组合”的方法来实现扩展

  • 使用情景

  • 系统需要在多重算法中选择一种

  • 重构系统时,将条件语句转换成对于策略的多态性调用

  • 优点(对比模板方法)

  • 将使用策略的人与策略的具体实现分离

  • 策略对象可以自由组合

  • 缺点

  • 策略模式仅仅封装了“算法的具体实现”,方便添加和替换算法,但它并不关心何时使用何种算法,这个必须由客户端来决定。

  • 策略模式和模板方法结合

  • 理解

  • 在运行时可以动态选择对应的策略实现,以减少if else的出现。

  1. 组合模式(Composite)

  • 定义

  • 是一种“对象的结构模式”

  • 应用

  • 文件系统

  • AWT控件

  • 理解

  • 把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。

  1. 装饰器模式(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进行增强。

用户头像

Jeff

关注

还未添加个人签名 2017.11.30 加入

还未添加个人简介

评论

发布
暂无评论
设计模式