目录
一、观察者模式
也叫发布-订阅模式,Spring 的事件驱动模型使用的是 观察者模式 ,Spring 中 Observer 模式常用的地方是 listener 的实现。具体的使用方式在基于JDK与Spring中的观察者模式
已经提供了,其原理简单概括下:事件机制的实现需要三个部分:事件源,事件,事件监听器
1、事件
所有的事件都需要继承 ApplicationEvent,ApplicationEvent 抽象类[事件] 继承自 JDK 的 EventObject,并且通过构造器参数 source 得到事件源,ApplicationContextEvent 表示 ApplicaitonContext 的容器事件。
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
2、事件监听器
所有的监听器都要实现 ApplicationListener 接口,这个接口只有一个 onApplicationEvent()方法,该方法接受一个 ApplicationEvent 或其子类对象作为参数,在方法体中,可以通过不同对 Event 类的判断来进行相应的处理。当事件触发时所有的监听器都会收到消息。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
3、事件源
ApplicationContext 是 spring 中的全局”应用上下文”,它负责实现了 ApplicationEventPublisher 接口。Applicationcontext 通过publishEvent() 方法发布 Event 广播给所有的监听器。
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
二、装饰者模式
装饰器模式又名包装(Wrapper)模式。装饰器模式以对客户端透明的方式拓展对象的功能,是继承关系的一种替代方案。
1.角色
抽象构件(Component)角色:给出一个抽象接口,已规范准备接收附加责任的对象。
具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。
组件接口
public interface Component {
public String getName();
}
具体组件实现类A
public class ComponentImplA implements Component {
private String name;
public ComponentImplA(String name){
this.name = name;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
}
具体组件实现类B
public class ComponentImplB implements Component {
private String name;
public ComponentImplB(String name){
this.name = name;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
}
装饰器实现组件接口
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public String getName() {
return component.getName();
}
}
具体的装饰器A,这里新增一个方法appendName;
public class DecoratorImplA extends Decorator {
public DecoratorImplA(Component component) {
super(component);
}
//增加额外的操作
public void appendName(String name){
System.out.println(this.component.getName()+name);
}
}
具体的装饰器B,这里重写原来的getName方法;
public class DecoratorImplB extends Decorator {
public DecoratorImplB(Component component) {
super(component);
}
@Override
public String getName() {
return super.getName()+"|append2";
}
}
测试类
public class DecoratorTest {
public static void main(String[] args) {
Component componentImplA = new ComponentImplA("componentA");
DecoratorImplA decoratorImplA = new DecoratorImplA(componentImplA);
decoratorImplA.appendName("|append1");
System.out.println(new DecoratorImplB(componentImplA).getName());;
}
}
2.分析
- 装饰器相较于继承来说,可以在运行时保持原来接口不变的情况下动态的给原对象增加新功能,而继承是静态的;
- 跟适配器比较
- 理想的装饰器模式的装饰者接口跟组件接口应该保持一模一样,这样每次传入一个组件进去,都只对组件接口的各个方法增加功能,返回依旧由组件接口接收,这样调用同一个对象的同一个方法会有不同的实现,调用者完全不必要知道具体调用的是哪个对象,这个也称之为透明装饰器;
- 如果装饰者接口跟组件接口不一致,装饰者接口对组件接口方法进行了扩增,也是增加了新功能,但是如果还是用原组件接口来接收的话,新增的方法需要向下转型才能使用,这就违背了装饰器的初衷,但是组件接口中的方法仍然可以正常使用,因此这种可称之为半透明装饰器;
- 如果只是需要将原来对象或者类转换成另外一个我们需要的对象接口,不增加新功能,这种就是适配器;
- 简单的来理解的话,装饰器用来新加功能,适配器只是用来转换功能;