深入理解.NET设计模式(1)

 

鸟随凤鸾,人伴贤良,得以共之,我之幸也。说的是鸟随着鸾凤可以飞的更高远,人和比自己境界高的相处,自己也会得到熏染进步。

一、概述

分享出来简单的心得,望探讨

依赖倒置

依赖注入

Adapter模式

Null模式

二、快速示例

 

部分代码:

 1 class ProductService
 2     {
 3 
 4         private ProductRepository _productRepository;
 5 
 6         public ProductService()
 7         {
 8             _productRepository=new ProductRepository();
 9         }
10 
11         public IList<Product> GerAllProductsIn(int category)
12         {
13             IList<Product> products;
14             string storagekey = string.Format("product_category_id_{0}",category);
15             products =(List<Product>) HttpContext.Current.Cache.Get(storagekey);
16 
17             if (products==null)
18             {
19                 products=_productRepository.GetAllProductsIn(category);
20                 HttpContext.Current.Cache.Insert(storagekey,products);
21             }
22             return products;
23         } 
24     }
ProductService

ProductService直接依赖于ProductRepostory属于强耦合。假设客户新产品上架,需要将ProductRepository替换为NewProductRepository,那么就势必要修改ProductService以及所有引用类ProductRepository

 三、重构

1、依赖倒置

那么究竟何为依赖倒置,它又如何解耦呢。

依赖倒置实际就是就是要依赖于抽象,不要依赖于具体。意思就是面对抽象进行,而不是面对实现进行编程,通过抽象解决客户与实现模块间的耦合关系。依赖倒置两大重要的原则:一是高层模块不应依赖于低层模块,都应依赖于抽象,二是具体实现也应依赖于抽象。

来看怎么做,定义IProductRepostory接口,使ProductRepostory依赖于接口 ,对ProductService重构也依赖于接口

 1 class ProductService
 2     {
 3 
 4         private IProductRepository _productRepository;
 5 
 6         public ProductService()
 7         {
 8             _productRepository=new ProductRepository();
 9         }
10 
11         public IList<Product> GerAllProductsIn(int category)
12         {
13             IList<Product> products;
14             string storagekey = string.Format("product_category_id_{0}",category);
15             products =(List<Product>) HttpContext.Current.Cache.Get(storagekey);
16 
17             if (products==null)
18             {
19                 products=_productRepository.GetAllProductsIn(category);
20                 HttpContext.Current.Cache.Insert(storagekey,products);
21             }
22             return products;
23         } 
24     }
ProductService

依赖倒置通过面对抽象从数据类型降低了耦合度,依赖倒置使高层模块依赖于抽象,即只关心new出来的是否是IProductRepository接口的对象而不关心new出来是谁。这样现在需要解决的就是具体实现的创建问题。

2、依赖注入

依赖注入从其初衷的角度解释就是:当类A完成某个工作需要创建B类的实例来协助的时候,把创建协助类B的工作提取出来从外部完成。

依赖注入三种形式:构造器,方法,属性。本文用构造器注入的方式介绍依赖注入

ProductService重构:

 1 public class ProductService
 2     {
 3         private IProductRepository _productRepository;
 4        
 5 
 6         public ProductService(IProductRepository productRepository)
 7         {           
 8             _productRepository = productRepository;
 9             
10         }
11     
12       ..................
13 
14          
15     }
ProductService

测试代码(即外部):

 1 namespace Patterns.QuickDemp.Tests
 2 {
 3     [TestFixture]
 4     public class ProductServiceTests
 5     {
 6         [Test]
 7         public void Test_Client()
 8         {
 9              //外部创建对象,任何继承抽象的对象皆可注入
10             AnyProductRepository anyproductrepository = new AnyProductRepository(); 
11             //注入
12             ProductService productService = new ProductService(anyproductrepository);
13             ...........
14             ..........
15 
16         }
17 
18 
19     }
20 }
Tests

 可以大胆的作如下设想:客户,商家,第三方支付的关系拿来类比,客户直接与商家交易是一种模式。现在依赖反转,银行卡,支付宝,现金券等支付方式全部继承某个接口,支付动作抽象出来,客户选择支付方式然后外部注入,第三方根据注入指定方式完成支付动作。

3、Adapter模式

 adapter模式意图描述:将一个类的接口转换成客户希望的接口

问题描述:用户自定义接口ICacheStorage.面向抽象过程中要让HttpContext成为一个实现用户自定义接口的实现。HttpContext是非用户编写的类,所以用到适配器模式

1 public interface ICacheStorage
2     {
3         void Remove(string key);
4         void Store(string key, object data);
5         T Retrieve<T>(string storageKey);
6     }
ICacheStorage
 1 public class HttpContextCacheAdapter : ICacheStorage
 2     {        
 3         public void Remove(string key)
 4         {
 5             HttpContext.Current.Cache.Remove(key);   
 6         }
 7 
 8         public void Store(string key, object data)
 9         {
10             HttpContext.Current.Cache.Insert(key, data);    
11         }
12 
13         public T Retrieve<T>(string key)
14         {
15             T itemStored = (T)HttpContext.Current.Cache.Get(key);
16             if (itemStored == null)
17                 itemStored = default(T);
18 
19             return itemStored;       
20         }       
21     }
HttpContextCacheAdapter

仍然依赖倒置依赖注入对Service重构如下:

 1 public class ProductService
 2     {
 3         private IProductRepository _productRepository;
 4         private ICacheStorage _cacheStorage;
 5 
 6         public ProductService(IProductRepository productRepository, ICacheStorage cacheStorage)
 7         {           
 8             _productRepository = productRepository;
 9             _cacheStorage = cacheStorage;
10         }
11 
12         public IList<Product> GetAllProductsIn(int categoryId)
13         {
14             IList<Product> products;
15             string storageKey = string.Format("products_in_category_id_{0}", categoryId);
16 
17             products = _cacheStorage.Retrieve<List<Product>>(storageKey);
18 
19             if (products == null)                
20             {
21                 products = _productRepository.GetAllProductsIn(categoryId);
22                 _cacheStorage.Store(storageKey, products);
23             }
24 
25             return products;
26         }
27     }
ProductService

4、Null Object 模式

空对象模式:在一些特殊的情况下用户不希望连带的执行某个动作,也不希望传递null在框架里做判断,就用到空对象模式。这个很容易理解,只是让附带动作变为do nothing 

 1 public class NullObjectCachingAdapter : ICacheStorage 
 2     {        
 3         public void Remove(string key)
 4         {
 5             // Do nothing
 6         }
 7 
 8         public void Store(string key, object data)
 9         {
10             // Do nothing
11         }
12 
13         public T Retrieve<T>(string storageKey)
14         {
15             return default(T);
16         }        
17     }
NullObjectCachingAdapter

 

 四、小结

深入理解.NET设计模式(1),古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。