一、简介
为了保证软件实现的简洁性,并且与模型保持一致,不管实际情况有多复杂,必须使用建模和设计的最佳实践,即让通过我们的编程技术(设计模型、指责驱动、契约式设计)充分地体现领域模型,并保持模型地健壮性和可扩展性,而不是单单地实现模型.某些决策设计能和模型紧紧地结合,这种结合要求我们注意每个元素地细节.
开发一个好的领域模型是一门艺术,而模型中的各个元素的实际设计和实现则相对系统化,将领域设计(也可以是软件系统中的其他关注点)与软件系统中的其他关注点(也可以是领域设计)分离使整个领域模型非常的清晰.根据不同模型的指责(特性)会使元素的意义更加鲜明.
二、实战
上图展示的模型驱动设计的基本构造块,当然实际开发中可能不止这些内容,可能还会有施加在实体上的一些契约还有一些特殊的计算规则、可能还有有一些复杂的实体运算,这些运算可能还需要使用一些设计模式去设计等等.但这个基本的构造.
下面通过C#代码来实现一个简单的用户订单计价系统,如下:
项目结构如下:
代码如下:
/// <summary>
/// 用户聚合根
/// </summary>
public class UserAggregate
{
/// <summary>
/// 抽象的用户
/// </summary>
public AbstractUser AbstractUser { get; set; }
}
/// <summary>
/// 抽象的用户,里面定义用户的基本属性
/// </summary>
public abstract class AbstractUser
{
/// <summary>
/// 值对象
/// </summary>
public abstract string UserName { get; set; }
/// <summary>
/// 值对象
/// </summary>
public abstract int Age { get; set; }
/// <summary>
/// 值对象 订单价格
/// </summary>
public abstract double OrderPrice { get; set; }
}
/// <summary>
/// 计价策略类,具体的计算规则,随着业务的变化,可已重新实现
/// </summary>
public class UserPriceAggregateStartegy : IUserPriceAggregateStartegies
{
public double CalculatePrice(UserAggregate user)
{
double totalfee = 0;
if (user.AbstractUser is WxUser)
{
//这里具体的优惠尺度可以去读取配置文件
totalfee=user.AbstractUser.OrderPrice * 0.8;
}
else if (user.AbstractUser is NormalUser)
{
totalfee=user.AbstractUser.OrderPrice;
}
return totalfee;
}
}
/// <summary>
/// 普通用户
/// </summary>
public class NormalUser : AbstractUser
{
public override string UserName { get; set; }
public override int Age { get; set; }
public override double OrderPrice { get; set; }
}
/// <summary>
/// 微信用户
/// </summary>
public class WxUser: AbstractUser
{
public override string UserName { get; set; }
public override int Age { get; set; }
/// <summary>
/// 微信用户的OpenId
/// </summary>
public string OpenId { get; set; }
/// <summary>
/// 值对象 订单价格
/// </summary>
public override double OrderPrice { get; set; }
}
/// <summary>
/// 用户计价聚合根约束
/// </summary>
public interface IUserPriceAggregateFactory
{
UserAggregate CalculatePrice(IUserPriceAggregateStartegies startegies);
}
/// <summary>
/// 用户聚合根工厂,按照计价策略生成对应的用户实体,这个类会暴露给外面的业务结构使用
/// 将业务逻辑的处理交给工厂类,这样做的好处,是减轻控制器的压力,也符合领域驱动设计的理念
/// </summary>
public class UserPriceAggregateFactory: IUserPriceAggregateFactory
{
private UserPriceAggregateFactory() { }
private UserAggregate _userAggregate;
public UserPriceAggregateFactory(UserAggregate userAggregate)
{
_userAggregate = userAggregate;
}
public UserAggregate CalculatePrice(IUserPriceAggregateStartegies startegies)
{
var price=startegies.CalculatePrice(_userAggregate);
_userAggregate.AbstractUser.OrderPrice = price;
return _userAggregate;
}
}
控制台调用代码如下:
class Program
{
static void Main(string[] args)
{
//拿到用户的输入
var normalUser = new WxUser()
{
UserName = "小超",
Age = 23,
OrderPrice = 6
};
//组成业务聚合根
var aggregare = new UserAggregate()
{
AbstractUser = normalUser
};
//生成用户计价类型的聚合根
var user = new UserPriceAggregateFactory(aggregare);
//生成具体的计价类型
var startegy = new UserPriceAggregateStartegy();
//生成计价过后的业务聚合根
var priceUser = user.CalculatePrice(startegy);
//随后将经过业务计算后的聚合根通过仓储初始化到数据库中
//.....省略
Console.WriteLine("当前用户的订单价格为:{0}", priceUser.AbstractUser.OrderPrice);
Console.ReadKey();
}
}
根据上面的代码可以得出一个基本的领域模型,如下:
注意下图
这个过程可以随意组合,可以通过Facade模式,组合多种策略,然后施加到用户聚合根上,得到最终的聚合根