单例模式
单例模式主要包括懒汉式、饿汉式、双重检查锁、静态内部类、枚举类。
注意的点:构造方法为private, 变量为private static。 方法是publish static。
状态模式
状态模式允许一个对象在其内部状态改变的时候改变其行为。比如投票系统,根据用户的不同投票次数执行不同的代码。
策略模式
策略模式和状态模式实现比较类似,但是目的不一样,状态模式各个状态是平行的,策略模式的各个策略是可以相互替换的。
比如定义交通工具就可以选择策略模式。
工厂模式
简单工厂模式:不宜扩展
工厂方法模式:违背了避包原则
抽象工厂方法:扩展性好
责任链模式
实现了请求发送者与请求处理者之间的松耦合
可动态添加责任对象、删除责任对象、改变责任对象顺序,非常灵活
每个责任对象专注于做自己的事情,职责明确
责任链还可以做反转,比如chain 的request、response
装饰器模式
装饰器模式在Java体系中的经典应用是Java I/O
观察者模式
要将观察者注册到主题角色上。
JDK是有直接支持观察者模式的,就是java.util.Observer这个接口。
引入设计模式最主要的作用我认为就是两点:
1、去重复代码,使得代码更清晰、更易读、更易扩展
2、解耦,使得代码可维护性更好,修改代码的时候可以尽量少改地方
使用观察者模式可以很好地做到这两点。增加观察者,直接new出观察者并注册到主题对象之后就完事了,删除观察者,主题对象调用方法删除一下就好了,其余都不用管。主题对象状态改变,内部会自动帮我们通知每一个观察者
代理模式
JDK动态代理的代理类字节码在创建时,必须实现InvocationHandler接口,需要实现业务实现类所实现的接口作为参数。如果业务实现类是没有实现接口而是直接定义业务方法的话,就无法使用JDK动态代理了。
CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;会继承目标对象,需要重写方法,所以目标对象不能为final类。
jdk动态代理是由java内部的反射机制来实现的,也用到了asm,cglib动态代理底层则是借助asm来实现的。
JDK 类库常用的设计模式有哪些?
答:JDK 常用的设计模式如下:
1)工厂模式
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");
2)适配器模式
把其他类适配为集合类
List<Integer> arrayList = java.util.Arrays.asList(new Integer[]{1,2,3});
List<Integer> arrayList = java.util.Arrays.asList(1,2,3);
3)代理模式
如 JDK 本身的动态代理。
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();
}
4)单例模式
全局只允许有一个实例,比如:
Runtime.getRuntime();
5)装饰器
为一个对象动态的加上一系列的动作,而不需要因为这些动作的不同而产生大量的继承类。
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) ;
6)模板方法模式
定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中。
比如,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);
}
}
IO 使用了什么设计模式?
答:IO 使用了适配器模式和装饰器模式。
适配器模式:由于 InputStream 是字节流不能享受到字符流读取字符那么便捷的功能,借助 InputStreamReader 将其转为 Reader 子类,因而可以拥有便捷操作文本文件方法;
装饰器模式:将 InputStream 字节流包装为其他流的过程就是装饰器模式,比如,包装为 FileInputStream、ByteArrayInputStream、PipedInputStream 等。
Spring 中都使用了哪些设计模式?
代理模式:在 AOP 中有使用
单例模式:bean 默认是单例模式
模板方法模式:jdbcTemplate
工厂模式:BeanFactory
观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用,比如,ContextStartedEvent 就是 ApplicationContext 启动后触发的事件
适配器模式:Spring MVC 中也是用到了适配器模式适配 Controller
网友评论