行为型 模式(10种)
责任链
命令
迭代器
中介者
备忘录
观察者
状态
策略
模板方法
访问者
还有 解释器 模式
责 命 迭 中 解 备 观 状 策 模 访
责 命 中解迭备 观 状 策 模 访
模仿 中解迭备 策责 观状命
编写制作豆浆的程序,说明如下:
基本介绍
对原理类图的说明-即(模板方法模式的角色及职责)
beat
v.
(反复地)敲,击,打;狠打,猛抽;搅拌,混合;拍动,扇动(翅膀);(心脏)跳动,搏动;击败,战胜;抢……之先,赶在……之前;避开,避免
n.
敲,击;(音乐或诗歌的)强音拍;(经常去或经过的)路线,地点;以之字形航线抢风航行
adj.
<非正式>筋疲力尽,疲惫不堪;垮掉的一代的
bean
n.
豆,菜豆,豆科植物;籽实,豆形种子;用于强调丝毫,一点;<旧>脑袋;(Bean)描述Java的软件组件模型(Enterprise Java Bean)
v.
(用某物)击中(某人)头部
soya
n.
大豆,[作物]黄豆
peanut
英
/ˈpiːnʌt/
n.
花生,花生米;<非正式>很少的钱(peanuts);小片聚苯乙烯泡沫塑料(peanuts)
condiment
调味品;佐料
//抽象类,表示豆浆
public abstract class SoyaMilk {
//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
final void make() {
select();
addCondiments();
soak();
beat();
}
//选材料
void select() {
System.out.println("第一步:选择好的新鲜黄豆 ");
}
//添加不同的配料, 抽象方法, 子类具体实现
abstract void addCondiments();
//浸泡
void soak() {
System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
}
void beat() {
System.out.println("第四步:黄豆和配料放到豆浆机去打碎 ");
}
}
public class PeanutSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
System.out.println(" 加入上好的花生 ");
}
}
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
----制作花生豆浆----
第一步:选择好的新鲜黄豆
加入上好的花生
第三步, 黄豆和配料开始浸泡, 需要3小时
第四步:黄豆和配料放到豆浆机去打碎
应用实例要求
编写制作豆浆的程序,说明如下:
• 制作豆浆的流程 选材—>添加配料—>浸泡—>放到豆浆机打碎
• 通过添加不同的配料,可以制作出不同口味的豆浆
• 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的(红
豆、花生豆浆。。。 )
//抽象类,表示豆浆
public abstract class SoyaMilk {
//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
final void make() {
select();
if(customerWantCondiments()) {
addCondiments();
}
soak();
beat();
}
//添加不同的配料, 抽象方法, 子类具体实现
abstract void addCondiments();
//钩子方法,决定是否需要添加配料
boolean customerWantCondiments() {
return true;
}
}
public class PureSoyaMilk extends SoyaMilk{
@Override
void addCondiments() {
//空实现
}
@Override
boolean customerWantCondiments() {
//纯豆浆,返回false,不会调用 加配料的方法
return false;
}
}
System.out.println("----制作纯豆浆----");
SoyaMilk pureSoyaMilk = new PureSoyaMilk();
pureSoyaMilk.make();
----制作纯豆浆----
第一步:选择好的新鲜黄豆
第三步, 黄豆和配料开始浸泡, 需要3小时
第四步:黄豆和配料放到豆浆机去打碎
ConfigurableApplicationContext
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
void refresh() throws BeansException, IllegalStateException;
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
//模板 方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory. 里面是抽象方法
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
try {
//钩子方法
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
//钩子方法
// Initialize other special beans in specific context subclasses.
onRefresh();
}
catch (BeansException ex) {
// Propagate exception to caller.
throw ex;
}
finally {
resetCommonCaches();
}
}
}
}
//钩子 方法
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
protected void onRefresh() throws BeansException {
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//两个抽象方法
refreshBeanFactory();
return getBeanFactory();
}
//都是 抽象的方法
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
//对 抽象方法,进行了实现
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
this.beanFactory.setSerializationId(getId());
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
}
AbstractRefreshableConfigApplicationContext
模板方法模式的注意事项和细节
基本介绍
命令模式(Command Pattern): 在软件设计中,我们经常需要
向某些对象发送请求,但是并不知道请求的接收者是谁,也不知
道被请求的操作是哪个,
我们只需在程序运行时指定具体的请求接收者即可,此时,可以
使用命令模式来进行设计
命名模式使得请求发送者与请求接收者消除彼此之间的耦合,让
对象之间的调用关系更加灵活,实现解耦。
在命名模式中,会将一个请求封装为一个对象, 以便使用不同参
数来表示不同的请求(即命名),同时命令模式也支持可撤销的操作。
通俗易懂的理解:将军发布命令,士兵去执行。其中有几个角色:
将军(命令发布者)、士兵(命令的具体执行者)、命令(连接将
军和士兵)。
Invoker是调用者(将军), Receiver是被调用者(士兵),
MyCommand是命令,实现了Command接口,持有接收对象
Invoker 是调用者角色
Command: 是命令角色,需要执行的所有命令都在这里,可以是接口或抽象类
Receiver: 接受者角色,知道如何实施和执行一个请求相关的操作
ConcreteCommand: 将一个接受者对象与一个动作绑定,调用接受者相应的操作,实现execute
//创建命令接口
public interface Command {
//执行动作(操作)
public void execute();
//撤销动作(操作)
public void undo();
}
public class LightReceiver {
public void on() {
System.out.println(" 电灯打开了.. ");
}
public void off() {
System.out.println(" 电灯关闭了.. ");
}
}
public class LightOnCommand implements Command {
//聚合LightReceiver
LightReceiver light;
//构造器
public LightOnCommand(LightReceiver light) {
super();
this.light = light;
}
@Override
public void execute() {
//调用接收者的方法
light.on();
}
@Override
public void undo() {
//调用接收者的方法
light.off();
}
}
/**
* 没有任何命令,即空执行: 用于初始化每个按钮, 当调用空命令时,对象什么都不做
* 其实,这样是一种设计模式, 可以省掉对空判断
*/
public class NoCommand implements Command {
@Override
public void execute() {
}
@Override
public void undo() {
}
}
public class RemoteController {
// 开 按钮的命令数组
Command[] onCommands;
Command[] offCommands;
// 执行撤销的命令
Command undoCommand;
// 构造器,完成对按钮初始化
public RemoteController() {
onCommands = new Command[5];
offCommands = new Command[5];
for (int i = 0; i < 5; i++) {
onCommands[i] = new NoCommand();
offCommands[i] = new NoCommand();
}
}
// 给我们的按钮设置你需要的命令
public void setCommand(int no, Command onCommand, Command offCommand) {
onCommands[no] = onCommand;
offCommands[no] = offCommand;
}
// 按下开按钮
public void onButtonWasPushed(int no) { // no 0
// 找到你按下的开的按钮, 并调用对应方法
onCommands[no].execute();
// 记录这次的操作,用于撤销
undoCommand = onCommands[no];
}
// 按下开按钮
public void offButtonWasPushed(int no) { // no 0
// 找到你按下的关的按钮, 并调用对应方法
offCommands[no].execute();
// 记录这次的操作,用于撤销
undoCommand = offCommands[no];
}
// 按下撤销按钮
public void undoButtonWasPushed() {
undoCommand.undo();
}
}
//使用命令设计模式,完成通过遥控器,对电灯的操作
//创建电灯的对象(接受者)
LightReceiver lightReceiver = new LightReceiver();
//创建电灯相关的开关命令
LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
//需要一个遥控器
RemoteController remoteController = new RemoteController();
//给我们的遥控器设置命令, 比如 no = 0 是电灯的开和关的操作
remoteController.setCommand(0, lightOnCommand, lightOffCommand);
System.out.println("--------按下灯的开按钮-----------");
remoteController.onButtonWasPushed(0);
System.out.println("--------按下灯的关按钮-----------");
remoteController.offButtonWasPushed(0);
System.out.println("--------按下撤销按钮-----------");
remoteController.undoButtonWasPushed();
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
@Override
public void query(String sql, RowCallbackHandler rch) throws DataAccessException {
query(sql, new RowCallbackHandlerResultSetExtractor(rch));
}
}
@Override
public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
Assert.notNull(sql, "SQL must not be null");
//子类,同时又 充当了 士兵的角色
class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
@Override
public T doInStatement(Statement stmt) throws SQLException {
ResultSet rs = null;
}
@Override
public String getSql() {
return sql;
}
}
//调用 execute ,此方法 是在 jdbcTemplate 实现的
return execute(new QueryStatementCallback());
}
@Override
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
try {
Connection conToUse = con;
//doInStatement 就是上面 内部类 实现的一个方法
T result = action.doInStatement(stmtToUse);
handleWarnings(stmt);
return result;
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
//命令接口
public interface StatementCallback<T> {
T doInStatement(Statement stmt) throws SQLException, DataAccessException;
}
- StatementCallback 接口 ,类似命令接口(Command)
- class QueryStatementCallback implements StatementCallback, SqlProvider , 匿名内
部类, 实现了命令接口, 同时也充当命令接收者
- 命令调用者 是 JdbcTemplate , 其中execute(StatementCallback action) 方法中,调
用action.doInStatement 方法. 不同的 实现 StatementCallback 接口的对象,对应不同
的doInStatemnt 实现逻辑
- 另外实现 StatementCallback 命令接口的子类还有 QueryStatementCallback、
不同之处在于,正规的 命令模式:命令接收者(士兵),不会实现命令的。
命令模式的注意事项和细节
