命令模式-工作单元

404 阅读2分钟

摘要:工作单元是命令模式得一种具体应用,就以webapi操作数据库来说工作单元模式,一次请求,需要操作多个或多次操作数据库,如果每操作一次都直接提交给数据库,那有可能在某些瞬态错误导致没法完成所有操作而产生数据不一致,不考虑分布式事务,最好得做法就是把所有操作打包,最后一次性把操作提交给数据库,这样可以最大程度保证一致性。设计模式Github源码

下面我们拿redis操作来描述一个工作单元

Repository(仓储类):这是用来写操作命令的库

UnitOfWork(工作单元类):里边有一个委托List 用来存储仓储类的命令,凡是你在进程里调用的Repository的方法都会存储在此,这个类还有一个执行方法Save,就是最终一起执行所有命令的方法

工作单元除了有以上有点,还有其他方面的优点,例如:

你在 UnitOfWork Save()方法里可以把你想在提交redis之前执行的其他需要统一执行的方法也写在上面,比如设置公共key,过滤命令之类的,怎么样,是不是和aop编程就搭边了,分离了操作命令与持久化,让它们自成模块,可以抽象通用的Save接口,具体实现可以是各种数据库,这样切换数据库也能使原来的操作不用修改(当然要支持sql语句的,例如很多ORM也是使用这种方式)

but,不能仅仅说优点,在数据库持久化使用这种设计的缺点(我认为的)还是有的,比如你在设计数据库仓储时候你用这个设计方案,就没法执行完一条sql得到结果后拿这个结果来去做其他事情,好比如你主键是自增的,你想执行完sql拿到插入后的id,这种就没得办法了,因为这些命令是save时候才执行的,所以一般都会两套走起。

代码实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace UnitOfWork
{
    public class Model
    {
        public static Model CreateNew(string myKey)
        {
            return new Model()
            {
                Key = myKey
            };
        }
        public string Key { get; set; }
    }
    public class Repository
    {
        public string Add(Model model)
        {
            Console.WriteLine(model.Key);
            return "add command";
        }

        public string Update(Model model)
        {
            Console.WriteLine(model.Key);
            return "update command";
        }

        public string Delete(Model model)
        {
            Console.WriteLine(model.Key);
            return "delete command";
        }
    }

    public class UnitOfWork
    {
        public List<Func<string, string>> Commands { get; set; } = new List<Func<string, string>>();

        public void AddCommand(Func<string, string> repositoryFunc)
        {
            Commands.Add(repositoryFunc);
        }

        public void Save()
        {
            var publicKey = "PublicKey-";
            //执行委托集合命令
            var commandList = Commands.Select(c => c(publicKey)).ToList();

            //打包redis命令然后提交
            //code...
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            UnitOfWork uow = new UnitOfWork();

            Repository repository = new Repository();

            uow.AddCommand((publicKey) =>
            {
                var model = Model.CreateNew(publicKey + "AddKey");
                return repository.Add(model);
            });
            uow.AddCommand((publicKey) =>
            {
                var model = Model.CreateNew(publicKey + "UpdateKey");
                return repository.Update(model);
            });
            uow.AddCommand((publicKey) =>
            {
                var model = Model.CreateNew(publicKey + "DeleteKey");
                return repository.Delete(model);
            });

            Console.WriteLine("Hello World!");

            //到这里才把所有语句执行
            uow.Save();

            Console.ReadKey();
        }
    }
}