java面试-设计模式
背景:讲设计模式的时候,最好能够结合源码来进行理解,逼格更高
ps:强烈推荐,感觉看这一篇就够了
策略模式
泛型接口比较实用的使用场景就是用作策略模式的公共策略,比如 Java 解惑:Comparable 和 Comparator 的区别 中介绍的 Comparator,它就是一个泛型接口
策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。 这个模式涉及到三个角色:
● 环境(Context)角色:持有一个Strategy的引用。
● 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
● 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
认识策略模式:
策略模式的重心
策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。
算法的平等性
策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。
所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。
运行时策略的唯一性
运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。
公有的行为
经常见到的是,所有的具体策略类都有一些公有的行为。这时候,就应当把这些公有的行为放到共同的抽象策略角色Strategy类里面。当然这时候抽象策略角色必须要用Java抽象类实现,而不能使用接口。
这其实也是典型的将代码向继承等级结构的上方集中的标准做法
策略和模板设计模式区别
如大家所熟知的Spring Data模块,存在JDBCTemplate、RedisTemplate、MongoTemplate等均是典型的模板模式。又例如Spring MVC中各种处理handler,是典型的策略模式。
因此我们可以看到,策略模式的关注点更广,模板模式的关注点更深。而且两种模式可以一起使用,即具体某个策略下可以通过模板减少不同步骤的冗余代码。
优缺点
模式 优点 缺点
策略 横向扩展性好,灵活性高 客户端需要知道全部策略,若策略过多会导致复杂度升高
模板 可维护性好,纵向扩展性好 耦合性较高,子类无法影响父类公用模块代码
迭代器模式 iterator
适配器模式
容器中使用到了
https://www.bookstack.cn/read/Interview-Notebook/notes-Java%20%E5%AE%B9%E5%99%A8.md
java.util.Arrays#asList() 可以把数组类型转换为 List 类型。
@SafeVarargs public static <T> List<T> asList(T... a)
如果要将数组类型转换为 List 类型,应该注意的是参数列表为泛型的变长参数,因此不能使用基本类型数组作为参数,只能使用相应的包装类型数组。
Integer[] arr = {1, 2, 3};
List list = Arrays.asList(arr);
也可以使用以下方式生成 List。
List list = Arrays.asList(1,2,3);
模板模式
AQS是个底层框架,采用模板方法模式
观察者模式(发布订阅模式)
主题里面维护观察者的列表(数组或者list),有具体事件发生时候 通知到每一个观察者
装饰器模式(Warpper模式)
指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式
在装饰器模式中的角色有:
ps:可以参考关系图
抽象构件(Component)角色:给出一个抽象接口,已规范准备接收附加责任的对象。
具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类(inputstream)
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。
装饰模式的优点
装饰模式与继承关系的目的都是要拓展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者“除掉”一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。
通过不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出更多不同行为的组合。
装饰模式的缺点
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另外一方面,使用装饰模式会产生比使用继承关系所产生的更多的对象。而更多的对象会使得查找错误更为困难,特别是这些对象在看上去极为相似的时候。
使用场景:
运行时,你需要动态地为对象增加额外职责时。
当你需要一个能够代替子类的类,借助它提供额外方法时。
举例:
java IO中流的封装
Mybatis中缓存的配置