首页 > 代码库 > DoubanFm之设计模式(一)

DoubanFm之设计模式(一)

  前两版DoubanFm写的太戳,第一版可以忽略,当是熟悉WP手机的一些API。。

第二版用了比较多的依赖注入,熟悉了Messenger,过后越写越大,感觉不对,赶快打住。。现在开始好好思考各模块了。

在Http请求方面,在知道了Restful后还没有机会使用它,感觉Restful应该还不错,不过我还是为我的Http请求使用了下面的设计模式

一.工厂方法

1.抽象产品

UML有空再画,先上代码,

使用Rx建立抽象的Get类产品,如下:

 1 public  abstract class HttpGetMethodBase<T> 2     { 3             public virtual IObservable<T> Get(string Url)//设置虚拟方法是为了多态 但是这里不用设置应该也可以 4             { 5                 //多态既是为了用子类的方法 6                 //其实我这里不需要用子类的方法 7                 //写了应该也可以 8                 //只要注意子类的Override 9                 var func = Observable.FromAsyncPattern<HttpWebRequest, T>(Webrequest, WebResponse);10                 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(Url);11                 return func(request);12             }13            private  IAsyncResult Webrequest(HttpWebRequest request, AsyncCallback callbcak, object ob)14             {15                 return request.BeginGetResponse(callbcak, request);16             }17 18            //发的请求用的是父类的get,WebResponse用的是子类的19             protected    abstract T WebResponse(IAsyncResult result);20      }

作为抽象的产品,有些方法可以共享,比如Get方法。要重写的是WebResponse

2.具体产品

(1)返回stream的产品

 1   public class HttpGetStream : HttpGetMethodBase<Stream> 2     { 3         protected override Stream WebResponse(IAsyncResult result) 4         { 5             try 6             { 7                 var request = result.AsyncState as HttpWebRequest; 8                 HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); 9                 #region ignore10                 if (response.Cookies != null)11                 {12                     foreach (Cookie cookie in response.Cookies)13                     {14                         Debug.WriteLine(cookie.Value);15                     }16                 }17                 Debug.WriteLine(response.ContentType);18                 Debug.WriteLine(response.StatusDescription);19                 if (response.Headers["Set-Cookie"] != null)20                 {21                     //setting may write22                     Debug.WriteLine(response.Headers["Set-Cookie"]);23                 }24                 #endregion25                return  response.GetResponseStream();26             }27             catch28             {29                 Debug.WriteLine("WEBERROR");30                 return null;31             }32         }33     }

(2)返回string的产品

 1   public class HttpGetString : HttpGetMethodBase<string> 2     { 3         protected  override string WebResponse(IAsyncResult result) 4         { 5             try 6             { 7                 var request = result.AsyncState as HttpWebRequest; 8                 HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); 9                 #region ignore10                 if (response.Cookies != null)11                 {12                     foreach (Cookie cookie in response.Cookies)13                     {14                         Debug.WriteLine(cookie.Value);15                     }16                 }17                 Debug.WriteLine(response.ContentType);18                 Debug.WriteLine(response.StatusDescription);19                 if (response.Headers["Set-Cookie"] != null)20                 {21                     //setting may write22                     Debug.WriteLine(response.Headers["Set-Cookie"]);23                 }24                 #endregion25                 Stream stream = response.GetResponseStream();26                 using (StreamReader sr = new StreamReader(stream))27                 {28                     return sr.ReadToEnd(); 29                 }30             }31             catch 32             {33                 Debug.WriteLine("WEBERROR");34                 return null;35             }36         }37     }

(3)返回位图的产品

 1   public class HttpGetBitmapImage : HttpGetMethodBase<BitmapImage> 2     {  3         protected override BitmapImage  WebResponse(IAsyncResult result) 4         { 5             try 6             { 7                 var request = result.AsyncState as HttpWebRequest; 8                 HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); 9                 #region ignore10                 if (response.Cookies != null)11                 {12                     foreach (Cookie cookie in response.Cookies)13                     {14                         Debug.WriteLine(cookie.Value);15                     }16                 }17                 Debug.WriteLine(response.ContentType);18                 Debug.WriteLine(response.StatusDescription);19                 if (response.Headers["Set-Cookie"] != null)20                 {21                     //setting may write22                     Debug.WriteLine(response.Headers["Set-Cookie"]);23                 }24                 #endregion25                 Stream stream = response.GetResponseStream();26                 BitmapImage bitmapimage = new BitmapImage();27                 bitmapimage.SetSource(stream);28                 return bitmapimage;29             }30             catch31             {32                 Debug.WriteLine("WEBERROR");33                 return null;34             }35         }36     }

现在主要有三种产品,如果以后有返回音频的产品,就照搬就好了,这样便于扩展。

3.接口工厂(不叫抽象工厂是怕跟抽象工厂模式冲突)

(1)用于创建对象(产品)的接口

 interface IHttpGet<T>    {        HttpGetMethodBase<T> CreateHttpRequest();    }

(2)具体的工厂

具体工厂都用来创建具体的产品

1.string(get)工厂

1  public class StringHttpFactory:IHttpGet<string>2     {3          public HttpGetMethodBase<string>  CreateHttpRequest()4         {5             return new HttpGetString();6         }7     }

2.stream(get)工厂

1   public class StreamHttpFactory : IHttpGet<Stream>2     {3 4         public HttpGetMethodBase<Stream> CreateHttpRequest()5         {6             return new HttpGetStream();7         }8     }

3.位图工厂

1 public class BitmapImageHttpFactory : IHttpGet<BitmapImage>2     {3         public HttpGetMethodBase<BitmapImage> CreateHttpRequest()4         {5             return new HttpGetBitmapImage();6         }7     }

 

客户端调用:

客户端调用还是得知道具体的工厂型号,所以这里我打个问号,先看看代码吧

1   IHttpGet<string> factory = new StringHttpFactory();//string 工厂2             factory.CreateHttpRequest().Get("http://douban.fm/j/mine/playlist?from=mainsite&channel=0&kbps=128&type=n").Subscribe(3                 (result) =>4                 {5                   7                 });

代码new了一个具体的工厂,这里并没有达到真正的解耦,所以我考虑看能不能以后做

1。配置文件反射处理

2.依赖注入。

//to be continued................

 

 二.职责链

先看看背景。

虽然用Newtonsoft的json库很爽,但是面对复杂的json串,不能很好的面对它的变化,变化点在于,JToken[][][][][][][][][],中括号的个数未知,我不知道哪天出来的json串会有几个[],如果使用到解析json串的地方很多,这个中括号的数量会非常多,看着非常恶心。。。。。。。。当然也许Newtonsoft有解决办法,但是我没摸索出来。

1.Json串的多样性

json串是由Web服务端安排的,各种命名,各种key/vaule,客户端很难应对这种变。  

用职责链的效果是:客户端只用发出获得的json字符串,就可以获得与之对应的类,至于json串怎么被处理的,客户端不知道

上代码

 1   public abstract class RequestorBase<T> 2     { 3         protected RequestorBase<T> Successor; 4         internal void SetSucessor(RequestorBase<T> suc) 5         { 6             Successor = suc; 7         } 8         public abstract T ProcessRequest(string json);//抽象不依赖于具体,抽象依赖于抽象 9     }

10 public class Requestor1<T> : RequestorBase<T>11 {12 public override T ProcessRequest(string json)13 {14 try15 {16 return JsonConvert.DeserializeObject<T>(JToken.Parse(json)["song"].ToString());17 }18 catch19 {20 Debug.WriteLine("这个是在职责链中的该有的异常");21 return Successor.ProcessRequest(json);22 }23 }24 }25 public class Requestor2<T> : RequestorBase<T>26 {27 public override T ProcessRequest(string json)28 {29 try30 {31 return JsonConvert.DeserializeObject<T>(JToken.Parse(json)["song"][0].ToString());32 }33 catch34 {35 Debug.WriteLine("这个是在职责链中的该有的异常");36 return Successor.ProcessRequest(json);37 }38 }39 }40 public class Requestor3<T> : RequestorBase<T>41 {42 public override T ProcessRequest(string json)43 {44 Debug.WriteLine("在职责链中没有能找到处理请求的方法,返回Default");45 return default(T);46 //NO Chain 继续下去了47 }48 }

不同的职责人作不同的json串解析。

 

然后再使用

三.单例模式

使用单例模式来创建管理职责链,使用单例管理职责链的目的是职责链只负责处理json串,他们都是无状态的,所有把他们的方法装入内存就可以了。

 1   public class ManagerResponsibilityChain<T> 2     { 3        static private RequestorBase<T> _startrequestor; 4        static public RequestorBase<T> Instance_Startrequestor 5         { 6             get  7             { 8                 if (_startrequestor == null) 9                 {10                     Inital();11                 }12                 return _startrequestor; 13             }14         }15         private ManagerResponsibilityChain()16         {17            18         }19         static private void Inital()20         {21             _startrequestor = new Requestor1<T>();22             var secondrequestor = new Requestor2<T>();23             var thridrequestor = new Requestor3<T>();24             _startrequestor.SetSucessor(secondrequestor);25             secondrequestor.SetSucessor(thridrequestor);//requestor3 is the end 26         }27     }

今天就到这。。。感觉还是太菜。。

 

DoubanFm之设计模式(一)