plsql执行command命令控制台出现乱码_设计模式系列 — 命令模式

news/2024/7/7 19:02:34

c3adb1c50ed6df582fdc1b39028d1350.png
点赞再看,养成习惯,公众号搜一搜【一角钱技术】关注更多原创技术文章。本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章。

前言

  • 23种设计模式速记
  • 单例(singleton)模式
  • 工厂方法(factory method)模式
  • 抽象工厂(abstract factory)模式
  • 建造者/构建器(builder)模式
  • 原型(prototype)模式
  • 享元(flyweight)模式
  • 外观(facade)模式
  • 适配器(adapter)模式
  • 装饰(decorator)模式
  • 观察者(observer)模式
  • 策略(strategy)模式
  • 桥接(bridge)模式
  • 模版方法(template method)模式
  • 责任链(chain of responsibility)模式
  • 组合(composite)模式
  • 代理(proxy)模式
  • 备忘录(memento)模式
  • 持续更新中......

23种设计模式快速记忆的请看上面第一篇,本篇和大家一起来学习命令模式相关内容。

f81b5e4321293f535bcd4615b6bcacd8.png

模式定义

将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

在软件开发系统中,常常出现“方法的请求者”与“方法的实现者”之间存在紧密的耦合关系。这不利于软件功能的扩展与维护。例如,想对行为进行“撤销、重做、记录”等处理都很不方便,因此“如何将方法的请求者与方法的实现者解耦?”变得很重要,命令模式能很好地解决这个问题。

07dde09821c07c04440a88ed3d9cbc60.png

模板实现如下

package com.niuh.designpattern.command.v1;/*** <p>* 命令模式* </p>*/
public class CommandPattern {public static void main(String[] args) {Command cmd = new ConcreteCommand();Invoker ir = new Invoker(cmd);System.out.println("客户访问调用者的call()方法...");ir.call();}
}//抽象命令
interface Command {public abstract void execute();
}//具体命令
class ConcreteCommand implements Command {private Receiver receiver;ConcreteCommand() {receiver = new Receiver();}public void execute() {receiver.action();}
}//接收者
class Receiver {public void action() {System.out.println("接收者的action()方法被调用...");}
}//调用者
class Invoker {private Command command;public Invoker(Command command) {this.command = command;}public void setCommand(Command command) {this.command = command;}public void call() {System.out.println("调用者执行命令command...");command.execute();}
}

输出结果如下

客户访问调用者的call()方法...
调用者执行命令command...
接收者的action()方法被调用...

解决的问题

在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

模式组成

可以将系统中的相关操作抽象成命令,使调用者与实现者相关分离,其结构如下。

5e580f985cc389c2c47583f7eb9d4e65.png

实例说明

实例概况

结合命令模式,实现一个课程视频的打开和关闭。

32b81e81ae978d93c49a907485a9ce03.png

使用步骤

步骤1:声明执行命令的接口,拥有执行命令的抽象方法 execute()

interface Command {void execute();
}

步骤2:定义具体命令角色,创建打开课程链接 和 关闭课程连接

/*** 打开课程链接*/
class OpenCourseVideoCommand implements Command {private CourseVideo courseVideo;public OpenCourseVideoCommand(CourseVideo courseVideo) {this.courseVideo = courseVideo;}@Overridepublic void execute() {courseVideo.open();}
}/*** 关闭课程链接*/
class CloseCourseVideoCommand implements Command {private CourseVideo courseVideo;public CloseCourseVideoCommand(CourseVideo courseVideo) {this.courseVideo = courseVideo;}@Overridepublic void execute() {courseVideo.close();}
}

步骤3:定义接收者角色,执行命令功能的相关操作,是具体命令对象业务的真正实现者

class CourseVideo {private String name;public CourseVideo(String name) {this.name = name;}public void open() {System.out.println(this.name + "课程视频开放。");}public void close() {System.out.println(this.name + "课程视频关闭。");}
}

步骤4:创建User对象为请求的发送者,即请求者角色

class User {private List<Command> commands = new ArrayList<>();public void addCommand(Command command) {commands.add(command);}public void executeCommands() {commands.forEach(Command::execute);commands.clear();}
}

步骤4:测试执行

public class CommandPattern {public static void main(String[] args) {//命令接收者CourseVideo courseVideo = new CourseVideo("设计模式系列");//创建命令OpenCourseVideoCommand openCourseVideoCommand = new OpenCourseVideoCommand(courseVideo);CloseCourseVideoCommand closeCourseVideoCommand = new CloseCourseVideoCommand(courseVideo);//创建执行人User user = new User();//添加命令user.addCommand(openCourseVideoCommand);user.addCommand(closeCourseVideoCommand);//执行user.executeCommands();}
}

输出结果

设计模式系列课程视频开放。
设计模式系列课程视频关闭。

优点

  1. 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
  2. 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
  3. 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
  4. 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

缺点

可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。

应用场景

命令执行过程较为复杂且可能存在变化,需要对执行命令动作本身进行额外操作,此时可以考虑使用命令模式

命令模式的扩展

在软件开发中,有时将命令模式与组合模式联合使用,这就构成了宏命令模式,也叫组合命令模式。宏命令包含了一组命令,它充当了具体命令与调用者的双重角色,执行它时将递归调用它所包含的所有命令,其具体结构图如下:

a89b1b0244c2b29ce4fb687d7f8e65da.png

模版实现如下

package com.niuh.designpattern.command.v2;import java.util.ArrayList;/*** <p>* 组合命令模式* </p>*/
public class CompositeCommandPattern {public static void main(String[] args) {AbstractCommand cmd1 = new ConcreteCommand1();AbstractCommand cmd2 = new ConcreteCommand2();CompositeInvoker ir = new CompositeInvoker();ir.add(cmd1);ir.add(cmd2);System.out.println("客户访问调用者的execute()方法...");ir.execute();}
}//抽象命令
interface AbstractCommand {public abstract void execute();
}//树叶构件: 具体命令1
class ConcreteCommand1 implements AbstractCommand {private CompositeReceiver receiver;ConcreteCommand1() {receiver = new CompositeReceiver();}public void execute() {receiver.action1();}
}//树叶构件: 具体命令2
class ConcreteCommand2 implements AbstractCommand {private CompositeReceiver receiver;ConcreteCommand2() {receiver = new CompositeReceiver();}public void execute() {receiver.action2();}
}//树枝构件: 调用者
class CompositeInvoker implements AbstractCommand {private ArrayList<AbstractCommand> children = new ArrayList<AbstractCommand>();public void add(AbstractCommand c) {children.add(c);}public void remove(AbstractCommand c) {children.remove(c);}public AbstractCommand getChild(int i) {return children.get(i);}public void execute() {for (Object obj : children) {((AbstractCommand) obj).execute();}}
}//接收者
class CompositeReceiver {public void action1() {System.out.println("接收者的action1()方法被调用...");}public void action2() {System.out.println("接收者的action2()方法被调用...");}
}

输出结果如下

客户访问调用者的execute()方法...
接收者的action1()方法被调用...
接收者的action2()方法被调用...
命令模式还可以同备忘录(Memento)模式组合使用,这样就变成了可撤销的命令模式

源码中的应用

  • java.util.Timer类中scheduleXXX()方法
  • java Concurrency Executor execute() 方法
  • java.lang.reflect.Method invoke()方法
  • org.springframework.jdbc.core.JdbcTemplate
  • ......

在 JdbcTemplate 中的应用

在JdbcTemplate中命令模式的使用并没有遵从标准的命令模式的使用,只是思想相同而已。

在 Spring 的 JdbcTemplate 这个类中有 query() 方法,query() 方法中定义了一个内部类 QueryStatementCallback,QueryStatementCallback 又实现了 StatementCallback 接口,另外还有其它类实现了该接口,StatementCallback 接口中又有一个抽象方法 doInStatement()。在 execute() 中又调用了 query()。

ff45ad99ca9db72ac3dadcd31dea3bf6.png

StatementCallback充当的是命令角色,JdbcTemplate即充当调用者角色,又充当接收者角色。上面的类图只是为了方便理解,实际上,QueryStatementCallback 与 ExecuteStatementCallback是JdbcTemplate中方法的内部类,具体看源码中的内容。

部分源码分析

StatementCallback接口:

public interface StatementCallback<T> {T doInStatement(Statement stmt) throws SQLException, DataAccessException;
}

JdbcTemplate类:

public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {//相当于调用者发布的一个命令@Overridepublic <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {return query(sql, new RowMapperResultSetExtractor<T>(rowMapper));}//命令发布后由具体的命令派给接收者进行执行@Overridepublic <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {Assert.notNull(sql, "SQL must not be null");Assert.notNull(rse, "ResultSetExtractor must not be null");if (logger.isDebugEnabled()) {logger.debug("Executing SQL query [" + sql + "]");}//内部类,实现StatementCallback,相当于具体的命令class QueryStatementCallback implements StatementCallback<T>, SqlProvider {@Overridepublic T doInStatement(Statement stmt) throws SQLException {ResultSet rs = null;try {rs = stmt.executeQuery(sql);ResultSet rsToUse = rs;if (nativeJdbcExtractor != null) {rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);}return rse.extractData(rsToUse);}finally {JdbcUtils.closeResultSet(rs);}}@Overridepublic String getSql() {return sql;}}return execute(new QueryStatementCallback());}//相当于接收者,命令真正的执行者@Overridepublic <T> T execute(StatementCallback<T> action) throws DataAccessException {Assert.notNull(action, "Callback object must not be null");Connection con = DataSourceUtils.getConnection(getDataSource());Statement stmt = null;try {Connection conToUse = con;if (this.nativeJdbcExtractor != null &&this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {conToUse = this.nativeJdbcExtractor.getNativeConnection(con);}stmt = conToUse.createStatement();applyStatementSettings(stmt);Statement stmtToUse = stmt;if (this.nativeJdbcExtractor != null) {stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);}T result = action.doInStatement(stmtToUse);handleWarnings(stmt);return result;}catch (SQLException ex) {// Release Connection early, to avoid potential connection pool deadlock// in the case when the exception translator hasn't been initialized yet.JdbcUtils.closeStatement(stmt);stmt = null;DataSourceUtils.releaseConnection(con, getDataSource());con = null;throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);}finally {JdbcUtils.closeStatement(stmt);DataSourceUtils.releaseConnection(con, getDataSource());}}
}

PS:以上代码提交在 Githubhttps://github.com/Niuh-Study/niuh-designpatterns.git

文章持续更新,可以公众号搜一搜「 一角钱技术 」第一时间阅读, 本文 GitHub org_hejianhui/JavaStudy 已经收录,欢迎 Star。

http://lihuaxi.xjx100.cn/news/276683.html

相关文章

mysql半连接_mysql表的半连接,反连接导致的mysql性能优化剖析

[导读] 关于Oracle的半连接&#xff0c;反连接&#xff0c;我一直认为这是一个能讲很长时间的话题&#xff0c;所以在我的新书《Oracle DBA工作笔记》中讲性能优化的时候&#xff0c;我花...关于Oracle的半连接&#xff0c;反连接&#xff0c;我一直认为这是一个能讲很长时间的…

visualstudio发布网站到服务器,发布到网站 - Visual Studio (Windows) | Microsoft Docs

使用 Visual Studio 将 Web 应用发布到网站01/29/2019本文内容可以使用“发布”工具将 ASP.NET、ASP.NET Core、.NET Core 和 Python 应用从 Visual Studio 发布到网站。 对于 Node.js&#xff0c;支持这些步骤但用户界面不同。先决条件安装有 Visual Studio 2019 并具有所选语…

AI拟音师出击,轻松骗过人类观众:你听到的电影音效可能来自它们

机器之心报道编辑&#xff1a;陈萍「我听见雨滴落在青青草地&#xff0c;我听见远方下课钟声响起……」多么浪漫的场景&#xff0c;但你有想过雨滴声和下课钟声是 AI 自动合成的吗&#xff1f;近日&#xff0c;一个叫做 AutoFoley 的机器学习程序横空出世&#xff0c;给电影拟音…

python django web项目的构建步骤(一)

Django 一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MVC的软件设计模式&#xff0c;即模型M&#xff0c;视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的。并于2005年7月在BSD许可证下发布。 1、安装好python djang…

导出表结构

http://wenku.baidu.com/view/979d6e3fee06eff9aef80766.html 选择&#xff1a; list of tables list of table columns 指定layout name data type length comment转载于:https://www.cnblogs.com/gaohuag/p/3304874.html

mysql random_Mysql中随机函数笔记

1&#xff0c;测试表结构&#xff1a;mysql> desc test_user;----------------------------------------------------------| Field | Type | Null | Key | Default | Extra |----------------------------------------------------------| id | int(11) | NO | PRI | NULL …

pythonrequest方法_解决Python requests 报错方法集锦

python版本和ssl版本都会导致 requests在请求https网站时候会出一些错误&#xff0c;最好使用新版本。 1 Python2.6x use requests 一台老Centos机器上跑着古老的应用&#xff0c;加了一个新模块之后报错 报错 InsecurePlatformWarning: A true SSLContext object is not avail…

科普:教你如何看懂 JavaGC 日志

点击上方“方志朋”&#xff0c;选择“设为星标”回复”666“获取新整理的面试资料来源&#xff1a;https://url.cn/5cvXPfUJVM GC 相关的参数-XX:PrintGC 输出 GC 日志 -XX:PrintGCDetails 输出 GC 的详细日志 -XX:PrintGCTimeStamps 输出 GC 的时间戳&#xff08;以基准时间的…