命令模式

第一点:将一个请求封装成为一个对象,从而让用户使用不同的请求将客户端参数化。 第二点:对请求排队或者纪录请求日志,以及支持撤销操作。 让我们程序扩展性更加好了,耦合降低了。

命令模式-应用场景: 当需要将方法调用包装成一个对象,以延时方法调用,或者让其他组件在对其内部实现细节不了解的情况下进行调用的时候可以使用命令模式

场景一:应用程序支持撤销和恢复 场景二:记录请求日志,当系统故障这些命令可以重新被执行 场景三:想用对象参数化一个动作以执行操作,并且用不同命令对象来替换回调函数

以命令模式进行分析:(思路) 管理器(请求者)--(调用)-->具体命令--(接口)-->接受者执行 命令模式至少有的4个角色:

  • 命令接口(抽象)(CommandProtocol):TMCommandProtocol
  • 具体命令(ConcrateCommand) 比如:1.向左-> TMLeftCommand 2.向右-> TMRightCommand 3.变型-> TMTransformCommand
  • 接受者(Reciever):TetrisMachine
  • 请求者 (命令管理器)(Invoker):TetrisMachineManger管理回调命令

案例需求:记录所有操作,支持回退(撤销)。


import Foundation
//命令接口
protocol CommandProtocol {
	func excute()
}

//具体命令
class TMLeftCommand: CommandProtocol {
	
	private var tm : TetrisMachine
	
	init(_ tm:TetrisMachine) {
		self.tm = tm
	}
		
	func excute() {
		self.tm.Toleft()
	}
}

class TMRightCommand: CommandProtocol {
	private var tm : TetrisMachine
	
	init(_ tm:TetrisMachine) {
		self.tm = tm
	}
	
	func excute() {
		
		self.tm.ToRight()
	}
}

class TMTransformCommand: CommandProtocol {
	private var tm : TetrisMachine
	
	init(_ tm:TetrisMachine) {
		self.tm = tm
	}
	
	func excute() {
		self.tm.ToTransform()
	}
}

//接受者
class TetrisMachine : NSObject {
	func Toleft(){
		print("left")
	}
	
	func ToRight(){
		print("right")
	}
	
	func ToTransform(){
		print("transform")
	}
}

//请求者
class TetrisMachineManger{
	private var commands = Array<CommandProtocol>()
	private var tm : TetrisMachine
	private var left : TMLeftCommand
	private var right : TMRightCommand
	private var transform : TMTransformCommand
	
	init(tm:TetrisMachine, left:TMLeftCommand,right:TMRightCommand,transform:TMTransformCommand) {
		self.left = left
		self.right = right
		self.transform = transform
		self.tm = tm
	}
	
	func Toleft(){
		self.left.excute()
		self.commands.append(TMLeftCommand(self.tm))
		
	}
	
	func ToRight(){
		self.right.excute()
		self.commands.append(TMRightCommand(self.tm))
	}
	
	func ToTransform(){
		self.transform.excute()
		self.commands.append(TMTransformCommand(self.tm))
	}
	
	func undo(){
		if self.commands.count > 0{
			self.commands.removeLast().excute()
		}
	}
}

//最后调用
let tm = TetrisMachine()
		let left = TMLeftCommand(tm)
		let right = TMRightCommand(tm)
		let transform = TMTransformCommand(tm)
		let manager = TetrisMachineManger(tm: tm, left: left, right: right, transform: transform)
		
		manager.Toleft()
		manager.ToRight()
		manager.ToTransform()
		manager.undo()
		
		//打印
left
right
transform
transform

5.1 命令模式 泛型设计 动态调用

什么是泛型:在定义的时候不需要指定类型,在使用的时候指定类型。(ObjectType)

1.声明文件->指定泛型->T(任意标识) 2.实现文件->指定具体类型(id万能指针->引用->指向任意对象)

[@interface](https://my.oschina.net/u/996807) NSMutableArray<ObjectType> : NSArray<ObjectType>
#import <Foundation/Foundation.h>
#import "TMCommandProtocol.h"
//T:表示任意类型标记(表示符)
[@interface](https://my.oschina.net/u/996807) GenericsCommand<T> : NSObject<TMCommandProtocol>
-(instancetype)init:(T)receiver block:(void(^)(T)) commandBlock;
+(id<TMCommandProtocol>)creatCommand:(T)receiver block:(void(^)(T)) commandBlock;
[@end](https://my.oschina.net/u/567204)

#import "GenericsCommand.h"
[@interface](https://my.oschina.net/u/996807) GenericsCommand<T>()
[@property](https://my.oschina.net/property) (nonatomic,strong)T receiver;
@property (nonatomic,strong)void(^commandblock)(T);
@end
@implementation GenericsCommand
//id 是指向泛型的引用
-(instancetype)init:(id)receiver block:(void(^)(id))commandBlock{
	self = [super init];
	if (self){
		self.receiver  = receiver ;
		self.commandblock = commandBlock;
	}
	return self;
}
-(void)execute{
	self.commandblock(self.receiver);
}
+(id<TMCommandProtocol>)creatCommand:(id)receiver block:(void(^)(id)) commandBlock{
	return [[GenericsCommand alloc]init:receiver block:commandBlock];
}
@end

#import <Foundation/Foundation.h>
#import "TetrisMachine.h"
@interface GenericsCommandManager : NSObject
-(instancetype)init:(TetrisMachine *)tm;
-(void)Toleft;
-(void)Toright;
-(void)Totransform;
-(void)undo;
-(void)Allundo;
@end

#import "GenericsCommandManager.h"
#import "GenericsCommand.h"
@interface GenericsCommandManager()
@property (nonatomic,strong)TetrisMachine *tm;
@property (nonatomic,strong)NSMutableArray *commands;
@end
@implementation GenericsCommandManager

-(instancetype)init:(TetrisMachine *)tm{
	self = [super init];
	if (self){
		self.tm = tm ;
		self.commands = [[NSMutableArray alloc]init];
	}
	return self;
}
-(void)Toleft{
	[self addCommand:@"Toleft"];
	[self.tm Toleft];//执行命令
}
-(void)Toright{
	[self addCommand:@"ToRight"];
	[self.tm ToRight];
}
-(void)Totransform{
	[self addCommand:@"ToTransform"];
	[self.tm ToTransform];
}

//管理器动态添加命令
-(void)addCommand:(NSString *)methodName{
	//根据方法名称,动态加载执行对象的方法
	SEL method = NSSelectorFromString(methodName);
	//添加动态命令
	[self.commands addObject:[GenericsCommand creatCommand:self.tm block:^(TetrisMachine *tm) {
		//执行回调
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
		[tm performSelector:method];
#pragma clang diagnostic pop
	}]];
	
}
-(void)undo{
	NSLog(@"撤销");
	if (self.commands.count > 0){
		//撤销
		[[self.commands lastObject]execute];
		//移除
		[self.commands removeLastObject];
		
	}
}
-(void)Allundo{
	NSLog(@"删除所有");
	//倒序co
	NSArray* reversedArray = [[self.commands reverseObjectEnumerator] allObjects];
	for (id<TMCommandProtocol> command in reversedArray){
		[command execute];
	}
	[self.commands removeAllObjects];
}
@end

5.2 命令模式 案例进阶 block闭包 && 并发(优化框架)

#import <Foundation/Foundation.h>
#import "TetrisMachine.h"
@interface BlockCommandManager : NSObject
-(instancetype)init:(TetrisMachine *)tm;
-(void)Toleft;
-(void)Toright;
-(void)Totransform;
-(void)undo;
-(void)Allundo;
@end

#import "BlockCommandManager.h"
typedef void (^BlockCommand)(TetrisMachine *tm);
@interface BlockCommandManager()
@property (nonatomic,strong)TetrisMachine *tm;
@property (nonatomic,strong)NSMutableArray *commands;
@property (nonatomic,strong)dispatch_queue_t queue;
@end
@implementation BlockCommandManager

-(instancetype)init:(TetrisMachine *)tm{
	self = [super init];
	if (self){
		self.tm = tm ;
		self.commands = [[NSMutableArray alloc]init];
		self.queue = dispatch_queue_create("Command", NULL);
	}
	return self;
}
-(void)Toleft{
	[self addCommand:@"Toleft"];
	[self.tm Toleft];//执行命令
}
-(void)Toright{
	[self addCommand:@"ToRight"];
	[self.tm ToRight];
}
-(void)Totransform{
	[self addCommand:@"ToTransform"];
	[self.tm ToTransform];
}

//管理器动态添加命令
-(void)addCommand:(NSString *)methodName{
	//并发 
	dispatch_sync(self.queue, ^{
		//根据方法名称,动态加载执行对象的方法
		SEL method = NSSelectorFromString(methodName);
		//添加动态命令  保存的是block
		[self.commands addObject:^(TetrisMachine *tm){
			#pragma clang diagnostic push
			#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
			[tm performSelector:method];
			#pragma clang diagnostic pop
		}];
	});
	
}
-(void)undo{
	NSLog(@"撤销");
	if (self.commands.count > 0){
		//撤销
		BlockCommand command =[self.commands lastObject];
		command(self.tm);
		//移除
		[self.commands removeLastObject];
	}
}
-(void)Allundo{
	NSLog(@"删除所有");
	//倒序co
	NSArray* reversedArray = [[self.commands reverseObjectEnumerator] allObjects];
	for (BlockCommand command in reversedArray){
		command(self.tm);
	}
	[self.commands removeAllObjects];
}
@end

5.3swift优化泛型命令

import UIKit

class GenericsCommand<T>: CommandProtocol {
	private var tm : T
	private var  block : (T)->Void
	
	init(receiver : T ,block:@escaping (T) -> Void) {
		self.tm = receiver;
		self.block = block
	}
	func excute() {
		self.block(self.tm)
	}
	
	
	class func creatCommand(receiver:T,block:@escaping (T)->Void)->CommandProtocol {
		return GenericsCommand (receiver: receiver, block: block)
	}
}

import UIKit

class GenericsCommandInvoke: NSObject {
	private var reveiver : TetrisMachine
	private var commands = Array<CommandProtocol>()
	
	init(reveiver:TetrisMachine) {
		self.reveiver = reveiver
	}
	
	func toLeft(){
		self.addCommand(method: TetrisMachine.Toleft)
		self.reveiver.Toleft()
	}
	
	func toRight(){
		self.addCommand(method: TetrisMachine.ToRight)
		self.reveiver.ToRight()
	}
	
	func toTransform(){
		self.addCommand(method: TetrisMachine.ToTransform)
		self.reveiver.ToTransform()
	}
	
	//使用的指定
	private func addCommand(method:@escaping(TetrisMachine)->()->(Void)){
		self.commands.append(GenericsCommand<TetrisMachine>(receiver: self.reveiver, block: { (tm) in
			method(tm)()
		}))
	}
	//modify  多个直接撤销
	func undo(){
		if self.commands.count>0{
			self.commands.removeLast().excute()
		}
	}
	
	func undoAll(){
		//		for commands in self.commands{
		//			commands.excute()
		//		}
		WrapperCommand(commands: self.commands).excute();
		self.commands.removeAll()
	}
}

5.4swift优化闭包命令

import UIKit

class BlockCommandInvoke: NSObject {
	private var queue = DispatchQueue(label: "Command")
	private var reveiver : TetrisMachine
	typealias BlockCommand = ((TetrisMachine) ->Void)
	private var commands = Array<BlockCommand>()
	
	init(reveiver:TetrisMachine) {
		self.reveiver = reveiver
	}
	
	func toLeft(){
		self.addCommand(method: TetrisMachine.Toleft)
		self.reveiver.Toleft()
	}
	
	func toRight(){
		self.addCommand(method: TetrisMachine.ToRight)
		self.reveiver.ToRight()
	}
	
	func toTransform(){
		self.addCommand(method: TetrisMachine.ToTransform)
		self.reveiver.ToTransform()
	}
	
	//
	private func addCommand(method:@escaping(TetrisMachine)->()->(Void)){
		self.queue.sync {
			self.commands.append({tm in
				method(tm)()
				})
		}
	}
	//modify  多个直接撤销
	func undo(){
		if self.commands.count > 0{
			self.commands.removeLast()(self.reveiver)
		}
	}
	
	func undoAll(){
		for command in self.commands{
			command(self.reveiver)
		}
		self.commands.removeAll()
	}
}

参考文章:https://www.jianshu.com/p/c62e1bc04bf1 NSUndoManager:https://nshipster.cn/nsundomanager/

转载于:https://my.oschina.net/u/2319073/blog/1851261

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值