设计模式及相关应用案例

用户头像
garlic
关注
发布于: 2020 年 10 月 04 日
设计模式及相关应用案例

设计模式

定义:



设计模式是一类问题的可复用的解决方案。 一般通过以下四个方面描述:



  • 名称: 设计模式的名称;

  • 待解问题: 要解决问题的何时运用这种模式,运行模式的上下文。

  • 解决方案: 解决方案的抽象。

  • 结论:这种方案的利弊, 主要描述方案弹性, 扩展性, 可移植性。

分类:



按照功能:

  • 创建模式:对类实例化过程的抽象。

  • 结构模式:将类或者对象进行组合。

  • 行为模式:对象职责的划分及算法抽象。



按照实现:



  • 类模式 : 继承方式实现,静态的

  • 对象模式: 组合方式实现, 动态的。

常见设计模式:



简单工厂



  通过Sorter工厂可以创建具体排序类, 排序类遵循interface接口。 如果要更换排序时, Client不需要进行变更只需要从Factory获取。





  工厂模式本身不符合的开闭原则结果方案: 通过配置文件方式加载获得构造实现类的变更。

改进后的简单工厂模式: 修改排序算法时需要修改SortFactory违反了开闭原则OCP, 可以通过将使用的排序算法存放到配置文件方式, 再通过反射机制进行加载, 从而不需要修改Factory来实现构造实现类的变更。



单例模式





私有构造函数: 使得外部无法通过new创建实例,

静态方法:能通过类获取类实例

私有静态变量:使得类实例化创建惟一对象。



  • 饿汉模式(推荐)

定义类时,单实例创建。

特点: 启动慢,引用快。



  • 懒汉模式

获取实例的时创建对象,需要synchronized同步等待,防止并发处理异常。

特点: 启动快,引用慢。



适配器模式



对于现有接口, 现有的类不满足,可以通过适配器模式使得完成原有类满足接口功能的实现, 实现高层模块定义好的接口,把接口里的实现委托父类(继承方式)或者 成员变量(组合方式)实现



类适配器:



对象适配器:(推荐)



应用: JDBC Driver, JDBC-ODBC Bridge



JUnit中的设计模式



JUnit单元测试的步骤

  • 初始化:setUp

  • 清除环境:tearDown

  • 书写测试方案: testXyz





模板方法



概念:

类的行为模式, 通过继承实现扩展积累确定号具体流程, 子类实现。

实现方法:

  • 抽象方法:(推荐)子类强制实现

  • 具体方法: 可以选择覆盖

  • 钩子方法: 父类不实现,子类选择覆盖。

策略模式



概念:

对象的行为模式,通过组合方法来实现扩展。

使用场景:

  • 重构系统:将条件语句转化未策略的多态调用, 通过工厂产生需要的策略模式。

  • 策略模式与模板结合使用:JUnit



JUnit调用策略接口Test接口 , 模板方法定义在TestCase中定义, 具体实现类继承TestCase, 按照具体的模板定义方法进行实现。



组合模式





概念:

对象的结构模式。很多情况先用于树形结构的数据上。 如文件系统或AWT控件。



装饰器模式



概念:

对象结构模式, 不改变客户端接口前提下,扩展现有对象, 如果要与装饰的对象使用统一接口,可以互相装饰。



相关应用:

Java Servlet, Java I/O 类库,同步化装饰 Collections.synchronizedList



Spring中的设计模式



依赖注入DI 控制反转IoC



A依赖B对象, A对象要构建B对象, 依赖注入,A对象不用创建B对象, B对象由外部创建,注入到A对象中。





Spring通过配置文件, 配置相关Bean结构信息,设置依赖对象,构建注入对象。 步骤如下:

  • 获取Class对象。

  • 直接调用无参数构造函数,实例化一个对象。

  • 获取属性节点,调用setter方法设置属性。

  • 获取属性名,S属性。

  • 构造Setter方法, 获取Setter的Method对象。

  • 调用Setter设置对象属性。



单例模式



由于Spring中容器管理的对象的创建, 单例实现上存在一个HashMap, 实现的缓存并保证唯一性。 步骤如下:



  • 检查缓存是否存在实例。 有直接反馈。

  • 如果空,锁定全局变量进行处理, 调用工厂getObject并更新到缓存。



Spring MVC模式



原有流程: 通过xml配置, url 匹配到具体的servlet, 当url匹配调用对应的servlet执行, sevrlet获得是容器,request对象获取其中数据, 处理完后构建html,通过response,进行输出。



Spring流程:大致流程没有很大变化, 处理过程有Spring框架完成, 使用Spring DispatcherServlet进行分发和处理。



实际案例



代码重构案例: Hive 支持标准SQL的案例



  • 职责拆分

transformer:实现sql语法点的转换sqlAST, 同时不同的语法点进行更细维度的拆分。

generator:将sqlAST转为Hive能够支持的AST结构树

将复杂的操作转为相对简单步骤,



  • 设计模式的应用



 装饰模式:SqlASTTransformer的构造, 每个Transforms用其他Transforms进行装饰。

public class TransformerBuilder {

private static SqlASTTransformer tf =
new RedundantSelectGroupItemTransformer(
new DistinctTransformer(
new GroupElementNormalizeTransformer(
new PrepareQueryInfoTransformer(
new OrderByTransformer(
new OrderByFunctionTransformer(
new MinusIntersectTransformer(
new PrepareQueryInfoTransformer(
new UnionTransformer(
new Leftsemi2LeftJoinTransformer(
。。。



每个语法点会被其他Transforms进行语法检查。



@Override
public void transform(CommonTree tree, TranslateContext context) throws SqlXlateException {
tf.transformAST(tree, context);
trans(tree, context);
}
。。。



模板方法:



子类实现tranform方法,被父类的tranformAST调用,在父类中输出相关日志和时间。

@Override
public void transformAST(CommonTree tree, TranslateContext context) throws SqlXlateException {
String myself = this.getClass().getSimpleName();
long begin = System.currentTimeMillis();

transform(tree, context);
long end = System.currentTimeMillis();

// performance log
LOG.info(myself + " spend time(ms):" + (end - begin));
。。。



ASTgenerate 通用用到了模板方法。



参考及引用



架构师训练营作业-李智慧老师相关讲义

Photo by Keith Lobo from Pexels



用户头像

garlic

关注

还未添加个人签名 2017.11.15 加入

还未添加个人简介

评论

发布
暂无评论
设计模式及相关应用案例