组合命令模式
两个银行之间进行汇款:
public class BankAccount { private int balance; private int overdraft = -500; /// <summary> /// 存款 /// </summary> /// <param name="amount"></param> public void Remittance(int amount) { if (amount < 0) throw new ArgumentException("汇款金额错误"); balance += amount; } /// <summary> /// 取款 /// </summary> /// <param name="amount"></param> public bool Withdrawal(int amount) { if (amount < 0) return false; if (balance - amount < overdraft) { return false; } balance -= amount; return true; } public override string ToString() { return $"balance:{balance}"; } } public interface ICommand { void Call(); void Undo(); bool Success { get; set; } } public class BankCommand : ICommand { public enum OpType { 存款, 取款 } private BankAccount bankAccount; private OpType opType; private int amount; public bool Success { get; set; } public BankCommand(BankAccount bankAccount, OpType opType, int amount) { this.bankAccount = bankAccount; this.opType = opType; this.amount = amount; } public void Call() { switch (opType) { case OpType.存款: bankAccount.Remittance(amount); Success = true; Console.WriteLine($"{DateTime.Now}:存款 {amount} 余额:{bankAccount}"); break; case OpType.取款: Success=bankAccount.Withdrawal(amount); if (Success) Console.WriteLine($"{DateTime.Now}:取款 {amount} 余额:{bankAccount}"); break; default: break; } } public void Undo() { if (!Success) return; switch (opType) { case OpType.存款: bankAccount.Withdrawal(amount); Console.WriteLine($"{DateTime.Now}:存款取消 {amount} 余额:{bankAccount}"); break; case OpType.取款: bankAccount.Remittance(amount); Console.WriteLine($"{DateTime.Now}:取款取消 {amount} 余额:{bankAccount}"); break; default: break; } } } public class CompositeBank : List<BankCommand>, ICommand { public CompositeBank() { } public CompositeBank(IEnumerable<BankCommand> bankCommands):base(bankCommands) { } public virtual bool Success { get { return this.All(t => t.Success); } set { ForEach(t => t.Success = value); } } public virtual void Call() { ForEach(cmd => cmd.Call()); } public virtual void Undo() { foreach (var item in ((IEnumerable<BankCommand>)this).Reverse()) { if (item.Success) item.Undo(); } } } internal class MoneyTransfeCommand : CompositeBank { public MoneyTransfeCommand(BankAccount from, BankAccount to,int amount) { AddRange(new[] {new BankCommand(from, BankCommand.OpType.取款,amount), new BankCommand(to, BankCommand.OpType.存款,amount) }); } public override void Call() { BankCommand last = null; foreach (var item in this) { if (last==null|| last.Success) { item.Call(); last = item; } else { item.Undo(); break; } } } } class Program { static void Main(string[] args) { BankAccount from = new BankAccount(); from.Remittance(100); BankAccount to = new BankAccount(); var trans = new MoneyTransfeCommand(from, to, 500); trans.Call(); Console.WriteLine(from); Console.WriteLine(to); trans.Undo(); Console.WriteLine(from); Console.WriteLine(to); } }