值对象

 

表示描述性的、欠缺身份的概念

比如"余额",在大多数领域中,你会单独查询"余额"吗?不会,因为独立的"余额"没有任何意义,他必须附属于某一个实体才会拥有自身的概念

 

增强明确性

DDD的一切都是为了明确传递重要业务规则和领域逻辑,如果用字符串、整型这类基元类型的话,并不适合描述概念,所以,应该组合基元类型,并封装成明确表示其正在建模的高内聚对象

 

比较

尽管值对象没有身份,比较他们也是是至关重要的操作。通过他们的特性或价值来比较相等性

 

富含行为

值对象应该尽可能多的公开具有表述性的面向领域行为并封装状态。默认来说,所有基元类型都应该是私有的或受保护的(实体也是如此) 如:public string Name{get; private set;}  ,只有当有足够合理的理由时,才能打破封装让其变成公共的

 

自验性

值对象必须保证状态有效(实体也是如此),它们自身就要单独负责确保满足这一需求,当创建值对象实例时,如果参数与规则不一致则构造函数里必须抛出异常。如Money可能会有两个领域规则:1.精确到两位小数。 2.不能为负数

 

不可变

一旦创建则不可变,每次修改都是返回新实例,因为不可变性通常更易于推断,并且天然属于线程安全,它只有很少的危险意外影响。并且不可变对象性能更好,因为为了保证对象状态完整性(避免数据撕裂)一般都会加锁,而不可变对象由于每次都返回新实例,永远都是数据完整的,所以不用加锁操作,不过这也是缺点,当每次对象/集合操作都会返回个新值,而旧值依旧会保留一段时间,这会使内存有极大开销,也会给GC造成回收负担,如果某个场景需要在两种方式选择其一的话,一般情况还是返回新对象为优先选择。.NET里的DateTime就是一个不可变性的经典示例。不可变性还会支持可组合性:组合起来以创建新的值,如Money + Money = new Money

 

    public class Money : ValueObject<Money>
    {
        protected readonly decimal Value;

        public Money() : this( 0m )
        {
        }

        /// <summary>
        /// 构造函数创建,当创建逻辑简单时应用构造函数创建
        /// </summary>
        public Money( decimal value )
        {
            if( value % 0.01m != 0 )
            {
                throw new Exception( "必须精确到两位小数" );
            }

            if( value < 0 )
            {
                throw new Exception( "不能为负数" );
            }
            Value = value;
        }

        /// <summary>
        /// 工厂创建,当创建逻辑复杂时应用工厂创建
        /// </summary>
        public static Money Create( decimal value )
        {
            if( value % 0.01m != 0 )
            {
                throw new Exception( "必须精确到两位小数" );
            }

            if( value < 0 )
            {
                throw new Exception( "不能为负数" );
            }
            return new Money( value );
        }

        public Money Add( Money money )
        {
            return new Money( Value + money.Value );
        }

        public Money Subtract( Money money )
        {
            return new Money( Value - money.Value );
        }

        public static Money operator +( Money left , Money right )
        {
            return new Money( left.Value + right.Value );
        }

        public static Money operator -( Money left , Money right )
        {
            return new Money( left.Value - right.Value );
        }

        /// <summary>
        /// 值对象比较,基于特性
        /// </summary>
        protected override IEnumerable<object> GetAttributesToIncludeInEqualityCheck()
        {
            return new List<object>() { Value };
        }
    }

    class Program
    {
        static void Main( string[] args )
        {
            var m = new Money( 100 );
            var m2 = new Money( 50 );

            var result = m - m2;
            var result2 = m + m2;
        }
    }
View Code

 

posted @ 2016-10-14 08:54  韬韬韬你羞得无礼  Views(300)  Comments(0Edit  收藏  举报