package com.linewell.modeldesgin.command import scala.collection.mutable.ArrayBuffer /** * 加法类,请求接收者 * Created by ctao on 2015/8/30. */ class Adder { /** * 计算器初始值 */ private var num = 0 /** * 加法操作 * @param value 传入值 * @return 计算结果 */ def add(value: Int) = { num += value num } } /** * 抽象命令类 */ abstract class AbstractCommand { /** * 命令执行方法 * @param value 数值 * @return */ def execute(value: Int): Int /** * 命令撤销方法 * @return 撤消后数值 */ def undo(): Int /** * 二次撤销方法 * @return 二次撤销后数值 */ def redo(): Int } /** * 具体命令类 */ class AddCommand extends AbstractCommand { /** * 值栈存放传入数值,用于进行undo */ private val values = new ArrayBuffer[Int]() /** * 值栈存放undo数值,用于redo */ private val valuesRedo = new ArrayBuffer[Int]() /** * 请求接收者 */ val adder = new Adder /** * 执行过程中将操作数放入值栈 * @param value 数值 * @return */ override def execute(value: Int) = { values += value adder.add(value) } /** * 如果是栈底,则不可undo,返回初始的num * 否则进行撤销,从值栈取最后一个值并加上相反数,并设置temp用于后续的redo * @return 撤消后数值 */ override def undo() = { values.length match { case 0 => println("不可undo"); adder.add(0) case _ => val temp = values.remove(values.length - 1) valuesRedo += temp adder.add(-temp) } } /** * 如果是redo值栈为0,返回原值+0的方式获取原值,因为原值是私有对象,并不需要加入值栈 * 否则取redo队列最后一个,加入值栈队列并执行加法 * @return 二次撤销后数值 */ override def redo() = { valuesRedo.length match { case 0 => println("不可redo"); adder.add(0) case _ => val temp = valuesRedo.remove(valuesRedo.length -1) values += temp adder.add(temp) } } } class CalculatorForm(command: AbstractCommand) { def compute(value: Int): Unit = { val i = command.execute(value) println(s"执行运算,运算结果为: $i") } def undo(): Unit = { val i = command.undo() println(s"执行undo,运算结果为: $i") } def redo(): Unit = { val i = command.redo() println(s"执行redo,运算结果为: $i") } }
package com.linewell.modeldesgin.command /** * 测试客户端 * Created by ctao on 2015/8/31. */ object ClientAdd extends App { val command: AbstractCommand = new AddCommand val form = new CalculatorForm(command) form.compute(10) form.compute(5) form.undo() form.undo() form.redo() form.redo() form.redo() form.undo() form.undo() form.undo() form.redo() form.compute(100)}
package com.linewell.modeldesgin.command import scala.collection.mutable.ArrayBuffer /** * 功能键设置窗口 * Created by ctao on 2015/8/30. */ case class FBSettingWindow(title: String) { /** * 用来存储按钮 */ private val functionButtons: ArrayBuffer[FunctionButton] = new ArrayBuffer[FunctionButton]() def addFunctionButton(functionButton: FunctionButton): Unit = functionButtons += functionButton def removeFunctionButton(functionButton: FunctionButton): Unit = functionButtons -= functionButton /** * 显示窗口和功能键 */ def display() = { println(s"显示窗口:$title") println("显示功能键:") functionButtons.foreach(fb => println(fb.name)) println("----------------") } } /** * 功能键类:请求发送者 * @param name 功能键名称 * @param command 维持一个抽象命令对象的引用 */ case class FunctionButton(name: String, command: Command) { /** * 发送请求的方法 */ def onClick(): Unit = { print("点击功能键:") command.execute() } } /** *抽象命令类 */ abstract class Command { def execute(): Unit } /** * 帮助命令类,具体命令类,维持对请求接收者的调用 */ object HelpCommand extends Command { /** * 其实本来可以直接使用单例对象,但这样可以把请求接受者表示更加清晰 */ val helpHandler = HelpHandler override def execute() = helpHandler.display() } /** *最小化命令类,具体命令类,维持对请求接收者的调用 */ object MinimizeCommand extends Command { val windowHandler = WindowHandler override def execute() = windowHandler.minimize() } /** * 窗口处理对象,请求的接收者 */ object WindowHandler { def minimize() = println("将窗口最小化到托盘") } /** * 帮助文档处理对象,请求的接收者 */ object HelpHandler { def display() = println("显示帮助文档") }package com.linewell.modeldesgin.command /** * 测试客户端 * Created by ctao on 2015/8/30. */ object Client extends App { val fbWindow = FBSettingWindow("功能键设置") /** * 通过设置抽象命令类对应的具体命令类 */ val command1: Command = HelpCommand val command2: Command = MinimizeCommand /** * 实现对功能键的注入 */ val fb1 = FunctionButton("功能键1", command1) val fb2 = FunctionButton("功能键2", command2) /** * 加入到窗口 */ fbWindow.addFunctionButton(fb1) fbWindow.addFunctionButton(fb2) // fbWindow.removeFunctionButton(fb1) fbWindow.display() /** * 调用功能键的业务方法 */ fb1.onClick() fb2.onClick() }package com.linewell.modeldesgin.command import scala.collection.mutable.ArrayBuffer /** * 命令队列模式 * Created by ctao on 2015/8/30. */ class CommandQueue { /** * 存放抽象命令类 */ private val commands: ArrayBuffer[CommandByQueue] = new ArrayBuffer[CommandByQueue]() def addCommand(commandByQueue: CommandByQueue) = commands += commandByQueue def removeCommand(commandByQueue: CommandByQueue) = commands -= commandByQueue /** * 批处理 */ def execute() = commands.foreach(_.execute()) } /** * 抽象命令类 */ abstract class CommandByQueue { def execute(): Unit } /** * 帮助命令类,具体命令类,维持对请求接收者的调用 */ object HelpCommandByQueue extends CommandByQueue { /** * 其实本来可以直接使用单例对象,但这样可以把请求接受者表示更加清晰 */ val helpHandler = HelpHandlerByQueue override def execute() = helpHandler.display() } /** * 最小化命令类,具体命令类,维持对请求接收者的调用 */ object MinimizeCommandByQueue extends CommandByQueue { val windowHandler = WindowHandlerByQueue override def execute() = windowHandler.minimize() } /** * 窗口处理对象,请求的接收者 */ object WindowHandlerByQueue { def minimize() = println("将窗口最小化到托盘") } /** * 帮助文档处理对象,请求的接收者 */ object HelpHandlerByQueue { def display() = println("显示帮助文档") } /** * 请求发送类 * @param commandQueue 命令队列 */ case class Invoker(commandQueue: CommandQueue) { /** * call方法,批处理 */ def call() = commandQueue.execute() }package com.linewell.modeldesgin.command /** * 批处理测试客户端 * Created by ctao on 2015/8/30. */ object ClientByQueue extends App { /** * 通过设置抽象命令类对应的具体命令类 */ val command1: CommandByQueue = HelpCommandByQueue val command2: CommandByQueue = MinimizeCommandByQueue /** * 加入命令队列 */ val commandQueue = new CommandQueue commandQueue.addCommand(command1) commandQueue.addCommand(command2) /** * 请求发送者 */ val invoker = Invoker(commandQueue) /** * 批处理 */ invoker.call() }package com.linewell.modeldesgin.command import java.io._ import scala.collection.mutable.ArrayBuffer /** * 配置文件操作类,请求的接收者,因为需要和command一起写文件,所以需要实现序列化接口 * Created by ctao on 2015/8/31. */ class ConfigOperator extends Serializable { /** * 插入 * @param args 参数 */ def insert(args: String) = println(s"add node:$args") /** * 修改 * @param args 参数 */ def modify(args: String) = println(s"alter node:$args") /** * 删除 * @param args 参数 */ def delete(args: String) = println(s"delete node:$args") } /** * 文件操作类 */ object FileUtil { /** * 写日志文件 * @param commands 参数集合 */ def writeCommands(commands: ArrayBuffer[LoggerCommand]): Unit = { var file: FileOutputStream = null var objOut: ObjectOutputStream = null try { file = new FileOutputStream("config.log") objOut = new ObjectOutputStream(new BufferedOutputStream(file)) objOut.writeObject(commands) } catch { case e: Exception => println("fail write commands"); e.printStackTrace() } finally { objOut.close() file.close() } } /** * 读日志文件 * @return 参数集合 */ def readCommands(): ArrayBuffer[LoggerCommand] = { var file: FileInputStream = null var commands = new ArrayBuffer[LoggerCommand]() var objIn: ObjectInputStream = null try { file = new FileInputStream("config.log") objIn = new ObjectInputStream(new BufferedInputStream(file)) commands = objIn.readObject().asInstanceOf[ArrayBuffer[LoggerCommand]] } catch { case e: Exception => println("fail read commands"); e.printStackTrace() } finally { objIn.close() file.close() } commands } } /** *抽象命令类,实现序列化接口将命令对象写文件 * @param name 命令名称 */ abstract class LoggerCommand(var name: String) extends Serializable { /** * 参数 */ protected var args: String = _ /** * 文件操作类 */ protected var configOperator: ConfigOperator = _ /** * 设置文件操作类 * @param config 文件操作类 */ def setConfigOperator(config: ConfigOperator) = configOperator = config /** * 带参数的执行方法 * @param args 参数 */ def execute(args: String): Unit /** * 不带参数的执行方法 */ def execute(): Unit } /** * 插入命令 * @param name 命令名称 */ class InsertCommand(name: String) extends LoggerCommand(name) { override def execute(args: String) = { this.args = args configOperator.insert(args) } override def execute() = configOperator.insert(args) } /** * 修改命令 * @param name 命令名称 */ class ModifyCommand(name: String) extends LoggerCommand(name) { override def execute(args: String) = { this.args = args configOperator.modify(args) } override def execute() = configOperator.modify(args) } /** * 删除命令 * @param name 命令名称 */ class DeleteCommand(name: String) extends LoggerCommand(name) { override def execute(args: String) = { this.args = args configOperator.delete(args) } override def execute() = configOperator.delete(args) } /** * 配置文件设置窗口类,请求的发送者 */ class ConfigSettingWindow { private var loggerCommand: LoggerCommand = _ /** * 存放命令操作对象的集合 */ private var commands = new ArrayBuffer[LoggerCommand]() /** * 设置命令 * @param command 命令对象 */ def setCommand(command: LoggerCommand) = loggerCommand = command /** * 执行方法,发送敏力请求 * @param args 参数 */ def call(args: String): Unit = { loggerCommand.execute(args) commands += loggerCommand } /** * 保存配置文件 */ def save() = FileUtil.writeCommands(commands) /** * 对配置文件中的命令对象依次调用 */ def recover() = FileUtil.readCommands().foreach(_.execute()) }package com.linewell.modeldesgin.command /** * 测试客户端 * Created by ctao on 2015/8/31. */ object ConfigClient extends App { var co = new ConfigOperator var loggerCommand: LoggerCommand = null loggerCommand = new InsertCommand("add") loggerCommand.setConfigOperator(co) var csw = new ConfigSettingWindow csw.setCommand(loggerCommand) csw.call("index") loggerCommand = new InsertCommand("add") loggerCommand.setConfigOperator(co) csw.setCommand(loggerCommand) csw.call("post") loggerCommand = new ModifyCommand("alter") loggerCommand.setConfigOperator(co) csw.setCommand(loggerCommand) csw.call("index") loggerCommand = new ModifyCommand("alter") loggerCommand.setConfigOperator(co) csw.setCommand(loggerCommand) csw.call("post") println("--------------------") println("save config") csw.save() println("--------------------") println("recover config") println("--------------------") csw.recover() }