June's Studio.

设计模式

字数统计: 2.2k阅读时长: 8 min
2023/04/05

JDK 中有哪些设计模式?

参考答案:JDK 常用的设计模式如下:

① 工厂模式

java.text.DateFormat 工具类,它用于格式化一个本地日期或者时间。

public final static DateFormat getDateInstance();

public final static DateFormat getDateInstance(int style);

public final static DateFormat getDateInstance(int style,Locale locale);

加密类

KeyGenerator keyGenerator = KeyGenerator.getInstance(“DESede”);

Cipher cipher = Cipher.getInstance(“DESede”);

② 适配器模式

把其他类适配为集合类

List arrayList = java.util.Arrays.asList(new Integer[]{1,2,3});

List arrayList = java.util.Arrays.asList(1,2,3);

③ 代理模式

JDK Proxy 动态代理的实现如下:

interface Animal {

void eat();

}

class Dog implements Animal {

@Override

public void eat() {

System.out.println(“The dog is eating”);

}

}

class Cat implements Animal {

@Override

public void eat() {

System.out.println(“The cat is eating”);

}

}

// JDK 代理类

class AnimalProxy implements InvocationHandler {

private Object target; // 代理对象

public Object getInstance(Object target) {

this.target = target;

// 取得代理对象

return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println(“调用前”);

Object result = method.invoke(target, args); // 方法调用

System.out.println(“调用后”);

return result;

}

}

public static void main(String[] args) {

// JDK 动态代理调用

AnimalProxy proxy = new AnimalProxy();

Animal dogProxy = (Animal) proxy.getInstance(new Dog());

dogProxy.eat();

}

④ 单例模式

全局只允许有一个实例,比如:

Runtime.getRuntime();

⑤ 装饰器模式

为一个对象动态的加上一系列的动作,而不需要因为这些动作的不同而产生大量的继承类。

java.io.BufferedInputStream(InputStream);

java.io.DataInputStream(InputStream);

java.io.BufferedOutputStream(OutputStream);

java.util.zip.ZipOutputStream(OutputStream);

java.util.Collections.checkedList(List list, Class type) ;

⑥ 模板方法模式

定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中。

比如,Arrays.sort() 方法,它要求对象实现 Comparable 接口。

class Person implements Comparable{

private Integer age;

public Person(Integer age){

this.age = age;

}

@Override

public int compareTo(Object o) {

Person person = (Person)o;

return this.age.compareTo(person.age);

}

}

public class SortTest(){

public static void main(String[] args){

Person p1 = new Person(10);

Person p2 = new Person(5);

Person p3 = new Person(15);

Person[] persons = {p1,p2,p3};

//排序

Arrays.sort(persons);

}

}

问题:Spring 中有哪些设计模式?

参考答案:Spring 框架使用的设计模式如下:

    代理模式:在 AOP 中有使用;

    单例模式:bean 默认是单例模式;

    模板方法模式:jdbcTemplate;

    工厂模式:BeanFactory;

    观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用,比如,ContextStartedEvent 就是 ApplicationContext 启动后触发的事件;

    适配器模式:Spring MVC 中也是用到了适配器模式适配 Controller。

问题:MyBatis 中有哪些设计模式?

参考答案:MyBatis 源码中的几个主要设计模式,即工厂模式、建造者模式、单例模式、适配器模式、代理模式、模板方法模式等,具体内容如下。

① 工厂模式

工厂模式想必都比较熟悉,它是 Java 中最常用的设计模式之一。工厂模式就是提供一个工厂类,当有客户端需要调用的时候,只调用这个工厂类就可以得到自己想要的结果,从而无需关注某类的具体实现过程。这就好比你去餐馆吃饭,可以直接点菜,而不用考虑厨师是怎么做的。

工厂模式在 MyBatis 中的典型代表是 SqlSessionFactory。SqlSession 是 MyBatis 中的重要 Java 接口,可以通过该接口来执行 SQL 命令、获取映射器示例和管理事务,而 SqlSessionFactory 正是用来产生 SqlSession 对象的,所以它在 MyBatis 中是比较核心的接口之一。

② 建造者模式

建造者模式指的是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。也就是说建造者模式是通过多个模块一步步实现了对象的构建,相同的构建过程可以创建不同的产品。

例如,组装电脑,最终的产品就是一台主机,然而不同的人对它的要求是不同的,比如设计人员需要显卡配置高的;而影片爱好者则需要硬盘足够大的(能把视频都保存起来),但对于显卡却没有太大的要求,我们的装机人员根据每个人不同的要求,组装相应电脑的过程就是建造者模式。

建造者模式在 MyBatis 中的典型代表是 SqlSessionFactoryBuilder。普通的对象都是通过 new 关键字直接创建的,但是如果创建对象需要的构造参数很多,且不能保证每个参数都是正确的或者不能一次性得到构建所需的所有参数,那么就需要将构建逻辑从对象本身抽离出来,让对象只关注功能,把构建交给构建类,这样可以简化对象的构建,也可以达到分步构建对象的目的,而 SqlSessionFactoryBuilder 的构建过程正是如此。

③ 单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,此模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。

单例模式也比较好理解,比如一个人一生当中只能有一个真实的身份证号,每个收费站的窗口都只能一辆车子一辆车子的经过,类似的场景都是属于单例模式。单例模式在 MyBatis 中的典型代表是 ErrorContext。

ErrorContext 是线程级别的的单例,每个线程中有一个此对象的单例,用于记录该线程的执行环境的错误信息。

④ 适配器模式

适配器模式是指将一个不兼容的接口转换成另一个可以兼容的接口,这样就可以使那些不兼容的类可以一起工作。

例如,最早之前我们用的耳机都是圆形的,而现在大多数的耳机和电源都统一成了方形的 typec 接口,那之前的圆形耳机就不能使用了,只能买一个适配器把圆形接口转化成方形的,

而这个转换头就相当于程序中的适配器模式,适配器模式在 MyBatis 中的典型代表是 Log。

MyBatis 中的日志模块适配了以下多种日志类型:

    SLF4J

    Apache Commons Logging

    Log4j 2

    Log4j

    JDK logging

⑤ 代理模式

代理模式指的是给某一个对象提供一个代理对象,并由代理对象控制原对象的调用。

代理模式在生活中也比较常见,比如我们常见的超市、小卖店其实都是一个个“代理”,他们的最上游是一个个生产厂家,他们这些代理负责把厂家生产出来的产品卖出去。

代理模式在 MyBatis 中的典型代表是 MapperProxyFactory。

MapperProxyFactory 的 newInstance() 方法就是生成一个具体的代理来实现某个功能。

⑥ 模板方法模式

模板方法模式是最常用的设计模式之一,它是指定义一个操作算法的骨架,而将一些步骤的实现延迟到子类中去实现,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。此模式是基于继承的思想实现代码复用的。

例如,我们喝茶的一般步骤都是这样的:

    把热水烧开

    把茶叶放入壶中

    等待一分钟左右

    把茶倒入杯子中

    喝茶

整个过程都是固定的,唯一变的就是泡入茶叶种类的不同,比如今天喝的是绿茶,明天可能喝的是红茶,那么我们就可以把流程定义为一个模板,而把茶叶的种类延伸到子类中去实现,这就是模板方法的实现思路。

模板方法在 MyBatis 中的典型代表是 BaseExecutor,在 MyBatis 中 BaseExecutor 实现了大部分SQL 执行的逻辑。

⑦ 装饰器模式

装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构,这种类型的设计模式属于结构型模式,它是作为现有类的一个包装。

装饰器模式在生活中很常见,比如装修房子,我们在不改变房子结构的同时,给房子添加了很多的点缀;比如安装了天然气报警器,增加了热水器等附加的功能都属于装饰器模式。

装饰器模式在 MyBatis 中的典型代表是 Cache。

Cache 除了有数据存储和缓存的基本功能外(由 PerpetualCache 永久缓存实现),还有其他附加的 Cache 类,比如先进先出的 FifoCache、最近最少使用的 LruCache、防止多线程并发访问的 SynchronizedCache 等众多附加功能的缓存类。

CATALOG
  1. 1. JDK 中有哪些设计模式?
  2. 2. 问题:Spring 中有哪些设计模式?
  3. 3. 问题:MyBatis 中有哪些设计模式?