zoukankan      html  css  js  c++  java
  • 值对象

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

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

    增强明确性

    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
  • 相关阅读:
    AIoT 2020 年分析
    TensorFlow解析常量、变量和占位符
    TensorFlow编程结构
    对端边缘云网络计算模式:透明计算、移动边缘计算、雾计算和Cloudlet
    Harmony生命周期
    立体显示与BCN双稳态手性向列相
    显示技术示例
    SystemML大规模机器学习,优化算子融合方案的研究
    改天有空看看 1
    gradle 123123
  • 原文地址:https://www.cnblogs.com/Scissors/p/5959030.html
Copyright © 2011-2022 走看看