Asp.Net Design Pattern Studynotes -- Part1

Asp.Net Design Pattern Studynotes -- Part1

 

let's start with an exampleto entry amazing OO world !

 

let's saynow we need to implement a small feature which need :ide

an entityclass: Product spa

businesslogic : List<Product>GetProductBy(Function<Product,bool> where);code

Service : List<Product> GetProductBy(Function<Product,bool>where);ip

 

1st Version

 

Entity:ssl

 

public classProduct{}


 

Logic:ci

 

public classProductRepositoryV1
    {
 
       public List<Product>GetProductBy(Func<Product,bool> where )
       {
           var products = newList<Product>();
           returnproducts.Where(where).ToList();
       }
    }


 

service:rem

 

classProductServiceV1
    {
        private ProductRepositoryV1 _productRespository;
        private List<Product>_cacheProduct ;
 
        public ProductServiceV1()
        {
            _productRespository = newProductRepositoryV1(); //1.instant
            _cacheProduct = newList<Product>();
        }
 
        public List<Product>GetProductListBy(Func<Product,bool> where)
        {
            var productInCache =_cacheProduct.Where(where);//3.in couple with BL
            if (!productInCache.Any())
            {
                var products =_productRespository.GetProductBy(where);
               _cacheProduct.AddRange(products); //2.also care about how to cache
                return products;
            }
            return productInCache.ToList();
        }
 
    }


 

 

But we cansee the deficiencies :it

 

For 1stVersion (Original Version):io

 

1.productServiceis in couple with ProductRepository .once productRespository changed method signature, service have to change code.table

solution: depend onabstract but not on concrete implementation

 

2.code is untestable .which need data base ready , but if data base can not connect ,meaning can not be tested.

solution: decoupleservice from business class

 

3.do multiple things .

a. cache thedata ,b. provice service .c. instance the repository object .

 

solution : do only one thing .

 

 

ok, nowlet's fix it !

2nd version :

 

Entity: same with above .

 

business:

 

interface IProductRespository//added interface fordependency inversion
    {
        List<Product>GetProductBy(Func<Product, bool> where);
    }
 class ProductRespositoryV2:IProductRespository
    {
        public List<Product>GetProductBy(Func<Product, bool> where)
        {
            var products = newList<Product>();
            returnproducts.Where(where).ToList();
        }
    }

 

 

 

Service :

 

class ProductServiceV2
    {
         private IProductRespository _productRespository;
        private List<Product>_cacheProduct ;
 
        public ProductServiceV2(IProductRespositorypr)
        {
            _productRespository = pr;
            _cacheProduct = newList<Product>();
        }
 
        public List<Product> GetProductListBy(Func<Product,bool> where)
        {
            var productInCache =_cacheProduct.Where(where);
            if (!productInCache.Any())
            {
                var products =_productRespository.GetProductBy(where);
               _cacheProduct.AddRange(products);
                return products;
            }
            return productInCache.ToList();
        }
    }
 
 

 

 

 

 

For 2ndVersion (Applydependency inversion + Dependency injection):

 

.still do multiple things:

a.still need to care about how to store . b. provide service

 

solution :put the responsibility of cache storage into another class,let service only depends on interface (IStorage)

 

 

3rd Version(Adapter pattern + Dependency inversion)

 

Entity :same with above .

 

business:

 

interface IProductRespository
    {
        List<Product> GetProductBy(Func<Product, bool> where);
    }
interface IStorage
    {
        void Add(IEnumerable<Product>products);
        IEnumerable<Product> Get(Func<Product, bool> where);
    }
 
class MemoryStorage:IStorage // Take the responsibility ofCache
    {
        private List<Product>_cacheProduct;
        public MemoryStorage()
        {
            _cacheProduct = newList<Product>();
        }
        public void Add(IEnumerable<Product> products)
        {
           _cacheProduct.AddRange(products);           
        }
 
        public IEnumerable<Product> Get(Func<Product, bool> where)
        {
            return _cacheProduct.Where(where);
        }
    }
 
class  ProductRespositoryV3:IProductRespository
    {
        public List<Product> GetProductBy(Func<Product, bool> where)
        {
            var products = new List<Product>();
            return products.Where(where).ToList();
        }
    }


 

 

Service:

 

class ProductServiceV3
    {
      // only dependson  abstract
         private IProductRespository_productRespository;
        private IStorage_cache;
 
  public ProductServiceV3(IProductRespository pr, IStorage storage)
        {
//new objalso do not care
            _productRespository = pr;
            _cache = storage;
        }
        public List<Product> GetProductListBy(Func<Product,bool> where)
        {
            var productInCache = _cache.Get(where);
            if (!productInCache.Any())
            {
                var products = _productRespository.GetProductBy(where);
                _cache.Add(products);
                return products;
            }
            return productInCache.ToList();
        }
    }


 

 

 

We Can see ,

1.Service only depends on Interface which is abstract(no more need to care about how to cache the data) ,

2.and for Service, storage and respository class only do one thing

3.for service ,respository ,storage all can be UT .

 

 

 

 

Whenever weare coding any class,always remember these 3 things :

 

1.only do one thing

2.depends only on abstract

3.always can be tested

相關文章
相關標籤/搜索