前两版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 ignore 10 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 write 22 Debug.WriteLine(response.Headers["Set-Cookie"]); 23 } 24 #endregion 25 return response.GetResponseStream(); 26 } 27 catch 28 { 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 ignore 10 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 write 22 Debug.WriteLine(response.Headers["Set-Cookie"]); 23 } 24 #endregion 25 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 ignore 10 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 write 22 Debug.WriteLine(response.Headers["Set-Cookie"]); 23 } 24 #endregion 25 Stream stream = response.GetResponseStream(); 26 BitmapImage bitmapimage = new BitmapImage(); 27 bitmapimage.SetSource(stream); 28 return bitmapimage; 29 } 30 catch 31 { 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 try 15 { 16 return JsonConvert.DeserializeObject<T>(JToken.Parse(json)["song"].ToString()); 17 } 18 catch 19 { 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 try 30 { 31 return JsonConvert.DeserializeObject<T>(JToken.Parse(json)["song"][0].ToString()); 32 } 33 catch 34 { 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 }
今天就到这。。。感觉还是太菜。。