纸上得来终觉浅,绝知此事要躬行。

 

规约模式学习总结

目前想到的可以使用规约模式的情况(以后想到了再补充):

1. 当有一组条件,被多处使用,且这些条件可以任意组合时,这个时候考虑使用规约模式来解耦;

 

下面看一下规约模式的简单实现:

    public interface ISpecification<T> where T : class
    {
        bool IsSatisfiedBy( T item );
    }

    public abstract class Specification<T> : ISpecification<T> where T : class
    {

        #region ISpecification<T> 成员

        public abstract bool IsSatisfiedBy( T item );

        #endregion

        public ISpecification<T> And( ISpecification<T> other )
        {
            return new AndSpecification<T>( this, other );
        }

        public ISpecification<T> Or( ISpecification<T> other )
        {
            return new OrSpecification<T>( this, other );
        }

        public ISpecification<T> Not()
        {
            return new NotSpecification<T>( this );
        }
    }

    public class AndSpecification<T> : Specification<T> where T : class
    {
        private readonly ISpecification<T> _left;
        private readonly ISpecification<T> _right;

        public AndSpecification( ISpecification<T> left, ISpecification<T> right )
        {
            if ( left == null ) throw new ArgumentNullException( "left" );
            if ( right == null ) throw new ArgumentNullException( "right" );

            this._left = left;
            this._right = right;
        }

        public override bool IsSatisfiedBy( T item )
        {
            return this._left.IsSatisfiedBy( item ) && this._right.IsSatisfiedBy( item );
        }
    }

    public class OrSpecification<T> : Specification<T> where T : class
    {
        private readonly ISpecification<T> _left;
        private readonly ISpecification<T> _right;

        public OrSpecification( ISpecification<T> left, ISpecification<T> right )
        {
            if ( left == null ) throw new ArgumentNullException( "left" );
            if ( right == null ) throw new ArgumentNullException( "right" );

            this._left = left;
            this._right = right;
        }

        public override bool IsSatisfiedBy( T item )
        {
            return this._left.IsSatisfiedBy( item ) || this._right.IsSatisfiedBy( item );
        }
    }

    public class NotSpecification<T> : Specification<T> where T : class
    {
        private readonly ISpecification<T> _left;

        public NotSpecification( ISpecification<T> left )
        {
            if ( left == null ) throw new ArgumentNullException( "left" );

            this._left = left;
        }

        public override bool IsSatisfiedBy( T item )
        {
            return !this._left.IsSatisfiedBy( item );
        }
    }

    public class NameSpecification : Specification<UserInfo>
    {
        public override bool IsSatisfiedBy( UserInfo item )
        {
            if ( item == null ) throw new ArgumentNullException( "item" );

            return item.Name.StartsWith( "JR", StringComparison.InvariantCultureIgnoreCase );
        }
    }

    public class AgeSpecification : Specification<UserInfo>
    {
        public override bool IsSatisfiedBy( UserInfo item )
        {
            if ( item == null ) throw new ArgumentNullException( "item" );

            return item.Age > 15;
        }
    }

    public class UserInfo
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

 

其中 UserInfo 是一个测试类,NameSpecification, AgeSpeicification 是两个规约模式的实现。下面看一下测试代码:

    public class SpecificationTest
    {
        public void RunTest()
        {
            var users = new List<UserInfo> { 
                new UserInfo{ Name = "JRoger1", Age = 11},
                new UserInfo{ Name = "roger1", Age = 12},
                new UserInfo{ Name = "JRoger2", Age = 18},
            };

            var nameSpec = new NameSpecification();
            var ageSpec = new AgeSpecification();
            var andSpec = nameSpec.And( ageSpec );
            var orSpec = nameSpec.Or( ageSpec );
            var notSpec = nameSpec.Not();

            Console.WriteLine( "Name Specification ... " );
            foreach ( var item in users )
            {
                if ( nameSpec.IsSatisfiedBy( item ) )
                {
                    Console.WriteLine( item.Name );
                }
            }

            Console.WriteLine();
            Console.WriteLine( "Age Specification ... " );
            foreach ( var item in users )
            {
                if ( ageSpec.IsSatisfiedBy( item ) )
                {
                    Console.WriteLine( item.Name );
                }
            }

            Console.WriteLine();
            Console.WriteLine( "And Specification ... " );
            foreach ( var item in users )
            {
                if ( andSpec.IsSatisfiedBy( item ) )
                {
                    Console.WriteLine( item.Name );
                }
            }

            Console.WriteLine();
            Console.WriteLine( "Or Specification ... " );
            foreach ( var item in users )
            {
                if ( orSpec.IsSatisfiedBy( item ) )
                {
                    Console.WriteLine( item.Name );
                }
            }

            Console.WriteLine();
            Console.WriteLine( "Not Specification ... " );
            foreach ( var item in users )
            {
                if ( notSpec.IsSatisfiedBy( item ) )
                {
                    Console.WriteLine( item.Name );
                }
            }

            Console.ReadLine();
        }
    }

 

关于规约模式,网上也有很多讲解的。关键还是理解其是在什么情景下提出来的方法。至于规约模式的实现,基本思想是一样的。但是各种语言有根据各种语言的特性实现的版本,C#版的有一个比较好的使用 Lambda 表达式实现的。上面的实现版本算是中规中矩的。

posted on 2015-01-23 22:04  JRoger  阅读(1673)  评论(2编辑  收藏  举报

导航