You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/** * Originator Implementation */publicclassCalculatorImpimplementsCalculator {
privateintfirstNumber;
privateintsecondNumber;
@OverridepublicPreviousCalculationToCareTakerbackupLastCalculation() {
// create a memento object used for restoring two numbersreturnnewPreviousCalculationImp(firstNumber, secondNumber);
}
@OverridepublicvoidrestorePreviousCalculation(PreviousCalculationToCareTakermemento) {
this.firstNumber = ((PreviousCalculationToOriginator) memento).getFirstNumber();
this.secondNumber = ((PreviousCalculationToOriginator) memento).getSecondNumber();
}
@OverridepublicintgetCalculationResult() {
// result is adding two numbersreturnfirstNumber + secondNumber;
}
@OverridepublicvoidsetFirstNumber(intfirstNumber) {
this.firstNumber = firstNumber;
}
@OverridepublicvoidsetSecondNumber(intsecondNumber) {
this.secondNumber = secondNumber;
}
}
/** * Memento Interface to Originator * * This interface allows the originator to restore its state */publicinterfacePreviousCalculationToOriginator {
intgetFirstNumber();
intgetSecondNumber();
}
/** * Memento interface to CalculatorOperator (Caretaker) */publicinterfacePreviousCalculationToCareTaker {
// no operations permitted for the caretaker
}
/** * Memento Object Implementation * <p> * Note that this object implements both interfaces to Originator and CareTaker */publicclassPreviousCalculationImpimplementsPreviousCalculationToCareTaker,
PreviousCalculationToOriginator {
privateintfirstNumber;
privateintsecondNumber;
publicPreviousCalculationImp(intfirstNumber, intsecondNumber) {
this.firstNumber = firstNumber;
this.secondNumber = secondNumber;
}
@OverridepublicintgetFirstNumber() {
returnfirstNumber;
}
@OverridepublicintgetSecondNumber() {
returnsecondNumber;
}
}
/** * CareTaker object */publicclassClient {
publicstaticvoidmain(String[] args) {
// program startsCalculatorcalculator = newCalculatorImp();
// assume user enters two numberscalculator.setFirstNumber(10);
calculator.setSecondNumber(100);
// find resultSystem.out.println(calculator.getCalculationResult());
// Store result of this calculation in case of errorPreviousCalculationToCareTakermemento = calculator.backupLastCalculation();
// user enters a numbercalculator.setFirstNumber(17);
// user enters a wrong second number and calculates resultcalculator.setSecondNumber(-290);
// calculate resultSystem.out.println(calculator.getCalculationResult());
// user hits CTRL + Z to undo last operation and see last resultcalculator.restorePreviousCalculation(memento);
// result restoredSystem.out.println(calculator.getCalculationResult());
// 110// -273// 110
}
}
You insert a quarter
You turned...
A gumball comes rolling out the slot...
You insert a quarter
Quarter returned
You turned, but there's no quarter
You need to pay first
You insert a quarter
You turned...
A gumball comes rolling out the slot...
You insert a quarter
You turned...
A gumball comes rolling out the slot...
You haven't insert a quarter
You insert a quarter
You can't insert another quarter
You turned...
A gumball comes rolling out the slot...
You insert a quarter
You turned...
A gumball comes rolling out the slot...
Oops, out of gumballs
You can't insert a quarter, the machine is sold out
You turned, but there are no gumballs
No gumball dispensed
customer1
order1
item1
order2
item1
order3
item1
customer2
order_a
item_a1
item_a2
item_a3
Number of customers: 2
Number of orders: 4
Number of items: 6
应用
JDK 中的应用
javax.lang.model.element.Element and javax.lang.model.element.ElementVisitor
javax.lang.model.type.TypeMirror and javax.lang.model.type.TypeVisitor
Spring 中的应用
在 Spring 源码中,org.springframework.beans.factory.config.BeanDefinitionVisitor 用于解析 bean 元数据并将其解析为 String (如具有作用域或工厂方法名称的 xml 属性)或 Object (如构造函数定义中的参数),已解析的值在与分析的 bean 关联的 BeanDefinition 实例中进行判断设置:
/** * Traverse the given BeanDefinition object and the MutablePropertyValues * and ConstructorArgumentValues contained in them. * @param beanDefinition the BeanDefinition object to traverse * @see #resolveStringValue(String) */publicvoidvisitBeanDefinition(BeanDefinitionbeanDefinition) {
visitParentName(beanDefinition);
visitBeanClassName(beanDefinition);
visitFactoryBeanName(beanDefinition);
visitFactoryMethodName(beanDefinition);
visitScope(beanDefinition);
visitPropertyValues(beanDefinition.getPropertyValues());
ConstructorArgumentValuescas = beanDefinition.getConstructorArgumentValues();
visitIndexedArgumentValues(cas.getIndexedArgumentValues());
visitGenericArgumentValues(cas.getGenericArgumentValues());
}
protectedvoidvisitParentName(BeanDefinitionbeanDefinition) {
StringparentName = beanDefinition.getParentName();
if (parentName != null) {
StringresolvedName = resolveStringValue(parentName);
if (!parentName.equals(resolvedName)) {
beanDefinition.setParentName(resolvedName);
}
}
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
责任链模式(Chain Of Responsibility)
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。
在责任链模式里,多个对象由每一个对象对其下家的引用连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求;客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
Handler:定义处理请求的接口,并且实现后继链(successor)。
实现
应用
JDK 中的应用
Spring 中的应用
在 Spring MVC 源码中,
HandlerExecutionChain
类存放了处理请求的 handler 和 interceptor 数组,主要负责请求的拦截器的执行和请求的处理,但是他本身不处理请求,只是将请求分配给在链上注册的处理器执行,这是一种责任链的实现方式,比如应用拦截器的前置处理:命令模式(Command)
允许将请求封装在一个对象内并附加一个回调动作,重点是命令不是由调用者直接执行,而是以回调的方式执行(请求被封装在命令对象之下,而请求的结果被发送到接收者)。
将命令封装成对象中有以下作用:
结构:
实现
设计一个遥控器,可以控制电灯开关。
应用
JDK 中的应用
Spring 中的应用
在 Spring 源码中,BeanFactory 加载的后处理器就是基于命令模式实现(ApplicationContext 则是自动加载)。其中从 BeanFactory 得到对象即获取命令的执行结果,而后处理器就是命令,
org.springframework.context.support.PostProcessorRegistrationDelegate
就是调用者(执行 postProcessBeanFactory 方法注册后处理器),目的是在 bean 构造初始化之前修改它(代码略)。解释器模式(Interpreter)
为语言创建解释器,通常由语言的语法和语法分析来定义。
实现
以下是一个规则检验器实现,具有 and 和 or 规则,通过规则可以构建一颗解析树,用来检验一个文本是否满足解析树定义的规则。
例如一颗解析树为 D And (A Or (B C)),文本 "D A" 满足该解析树定义的规则。
这里的 Context 指的是 String。
应用
JDK 中的应用
Spring 中的应用
SpEL(Spring Expression Language):即 Spring 表达式语言,在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与 Spring 功能完美整合(用来配置 Bean 定义等)。
在 Spring 源码中,由
org.springframework.expression
包中的ExpressionParser
实现分析和执行,转换为Expression
实例,上下文组件EvaluationContext
实现表示:输出“Overriden writer’s name”。对象的属性是通过一个表达式
name = #name
进行修改,而表达式(在context 中)只有在ExpressionParser
才能理解。迭代器模式(Iterator)
提供一种顺序访问聚合对象元素的方法,并且不暴露聚合对象的内部表示。
实现
应用
JDK 中的应用
中介者模式(Mediator)
集中相关对象之间复杂的沟通和控制方式。
实现
Alarm(闹钟)、CoffeePot(咖啡壶)、Calendar(日历)、Sprinkler(喷头)是一组相关的对象,在某个对象的事件产生时需要去操作其它对象,使用中介者模式可以将复杂的依赖结构变成星形结构:
应用
JDK 中的应用
备忘录模式(Memento)
在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。
实现
以下实现了一个简单计算器程序,可以输入两个值,然后计算这两个值的和。备忘录模式允许将这两个值存储起来,然后在某个时刻用存储的状态进行恢复。
实现参考:Memento Pattern - Calculator Example - Java Sourcecode
应用
JDK 中的应用
观察者模式(Observer)
观察者模式由观察者、观察事件和被观察者组成,当观察事件发生变化,由被观察者向观察者发起通知,使所有观察者都感知到变化。
定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。
主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。

主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。
观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。
实现
天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。
应用
JDK 中的应用
Spring 中的应用
在 Spring 源码中,观察者模式主要运用在应用上下文的事件监听中
org.springframework.context.ApplicationListener
,Listener 添加到 ApplicationContext 中,并注册到适当的时间多路广播器(存在多个监听器)。EventMulticaster 负责管理不同的 Listener 并向他们发布事件。状态模式(State)
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。
实现
应用
策略模式(Strategy)
策略模式定义了以不同的方式达到相同目的的几个对象(比如以不同的出行方式到达目的地)。
其定义一系列算法,封装每个算法并使它们可以互换,让算法独立于使用它的客户端。
与状态模式的比较:
实现
设计一个鸭子,它可以动态地改变叫声。这里的算法族是鸭子的叫声行为。
应用
JDK 中的应用
Spring 中的应用
在 Spring 源码中,资源加载器
ResourceLoader
提供了多个实现类,通过策略模式对传入的资源地址信息(classpath:com/beanfactory/beans.xml
)自动选择适合的底层资源实现类,为上层对资源的引用提供极大的便利。另一个例子是 bean 的实例化,通过动态代理的两种策略实现:JDK 动态代理和 CGLIB 动态代理,见
org.springframework.beans.factory.support.SimpleInstantiationStrategy
:另一个例子是 Spring AOP,
org.springframework.aop.framework.DefaultAopProxyFactory
实现了接口AopProxyFactory
,可根据不同的条件调用不同的代理策略,返回AopProxy
对象:模板方法模式(Template Method)
模板方法定义了类行为的骨架,以给定的顺序执行由子类定义的方法。
其定义算法框架并将一些步骤的实现延迟到子类。通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。
实现
冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样,要求复用那些相同步骤的代码。
应用
JDK 中的应用
Spring 中的应用
在 Spring 源码中,
org.springframework.context.support.AbstractApplicationContext
类包含了多个模板方法,比如:模板方法
obtainFreshBeanFactory
为具体方法,其定义了“先执行refreshBeanFactory
,再返回getBeanFactory
” 的执行结果的逻辑;但它只定义抽象方法的执行顺序,refreshBeanFactory
和getBeanFactory
的具体作用则交由子类实现。访问者模式(Visitor)
为一个对象结构(比如组合结构)增加新能力。
通过一个封装对象实现对目标对象的访问,可以在不改变目标对象的前提下定义作用于目标对象的操作。
实现
应用
JDK 中的应用
Spring 中的应用
在 Spring 源码中,
org.springframework.beans.factory.config.BeanDefinitionVisitor
用于解析 bean 元数据并将其解析为 String (如具有作用域或工厂方法名称的 xml 属性)或 Object (如构造函数定义中的参数),已解析的值在与分析的 bean 关联的 BeanDefinition 实例中进行判断设置:在这种情况下,他们只是访问方式,没有对访问者做任何补充的控制。
空对象模式(Null)
使用什么都不做的空对象来代替 NULL。
一个方法返回 NULL,意味着方法的调用端需要去检查返回值是否是 NULL,这么做会导致非常多的冗余的检查代码。并且如果某一个调用端忘记了做这个检查返回值,而直接使用返回的对象,那么就有可能抛出空指针异常。
实现
应用
Beta Was this translation helpful? Give feedback.
All reactions