组合命令模式

两个银行之间进行汇款:

    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);
        }
    }

 

posted @ 2022-05-26 13:44  后跳  阅读(40)  评论(0编辑  收藏  举报