DoubanFm之设计模式(一)
前两版DoubanFm写的太戳,第一版可以忽略,当是熟悉WP手机的一些API。。
第二版用了比较多的依赖注入,熟悉了Messenger,过后越写越大,感觉不对,赶快打住。。现在开始好好思考各模块了。
在Http请求方面,在知道了Restful后还没有机会使用它,感觉Restful应该还不错,不过我还是为我的Http请求使用了下面的设计模式
一.工厂方法
1.抽象产品
UML有空再画,先上代码,
使用Rx建立抽象的Get类产品,如下:
public abstract class HttpGetMethodBase<T>
{
public virtual IObservable<T> Get(string Url)//设置虚拟方法是为了多态 但是这里不用设置应该也可以
{
//多态既是为了用子类的方法
//其实我这里不需要用子类的方法
//写了应该也可以
//只要注意子类的Override
var func = Observable.FromAsyncPattern<HttpWebRequest, T>(Webrequest, WebResponse);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(Url);
return func(request);
}
private IAsyncResult Webrequest(HttpWebRequest request, AsyncCallback callbcak, object ob)
{
return request.BeginGetResponse(callbcak, request);
} //发的请求用的是父类的get,WebResponse用的是子类的
protected abstract T WebResponse(IAsyncResult result);
}
作为抽象的产品,有些方法可以共享,比如Get方法。要重写的是WebResponse
2.具体产品
(1)返回stream的产品
public class HttpGetStream : HttpGetMethodBase<Stream>
{
protected override Stream WebResponse(IAsyncResult result)
{
try
{
var request = result.AsyncState as HttpWebRequest;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
#region ignore
if (response.Cookies != null)
{
foreach (Cookie cookie in response.Cookies)
{
Debug.WriteLine(cookie.Value);
}
}
Debug.WriteLine(response.ContentType);
Debug.WriteLine(response.StatusDescription);
if (response.Headers["Set-Cookie"] != null)
{
//setting may write
Debug.WriteLine(response.Headers["Set-Cookie"]);
}
#endregion
return response.GetResponseStream();
}
catch
{
Debug.WriteLine("WEBERROR");
return null;
}
}
}
(2)返回string的产品
public class HttpGetString : HttpGetMethodBase<string>
{
protected override string WebResponse(IAsyncResult result)
{
try
{
var request = result.AsyncState as HttpWebRequest;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
#region ignore
if (response.Cookies != null)
{
foreach (Cookie cookie in response.Cookies)
{
Debug.WriteLine(cookie.Value);
}
}
Debug.WriteLine(response.ContentType);
Debug.WriteLine(response.StatusDescription);
if (response.Headers["Set-Cookie"] != null)
{
//setting may write
Debug.WriteLine(response.Headers["Set-Cookie"]);
}
#endregion
Stream stream = response.GetResponseStream();
using (StreamReader sr = new StreamReader(stream))
{
return sr.ReadToEnd();
}
}
catch
{
Debug.WriteLine("WEBERROR");
return null;
}
}
}
(3)返回位图的产品
public class HttpGetBitmapImage : HttpGetMethodBase<BitmapImage>
{
protected override BitmapImage WebResponse(IAsyncResult result)
{
try
{
var request = result.AsyncState as HttpWebRequest;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
#region ignore
if (response.Cookies != null)
{
foreach (Cookie cookie in response.Cookies)
{
Debug.WriteLine(cookie.Value);
}
}
Debug.WriteLine(response.ContentType);
Debug.WriteLine(response.StatusDescription);
if (response.Headers["Set-Cookie"] != null)
{
//setting may write
Debug.WriteLine(response.Headers["Set-Cookie"]);
}
#endregion
Stream stream = response.GetResponseStream();
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.SetSource(stream);
return bitmapimage;
}
catch
{
Debug.WriteLine("WEBERROR");
return null;
}
}
}
现在主要有三种产品,如果以后有返回音频的产品,就照搬就好了,这样便于扩展。
3.接口工厂(不叫抽象工厂是怕跟抽象工厂模式冲突)
(1)用于创建对象(产品)的接口
interface IHttpGet<T>
{
HttpGetMethodBase<T> CreateHttpRequest();
}
(2)具体的工厂
具体工厂都用来创建具体的产品
1.string(get)工厂
public class StringHttpFactory:IHttpGet<string>
{
public HttpGetMethodBase<string> CreateHttpRequest()
{
return new HttpGetString();
}
}
2.stream(get)工厂
public class StreamHttpFactory : IHttpGet<Stream>
{ public HttpGetMethodBase<Stream> CreateHttpRequest()
{
return new HttpGetStream();
}
}
3.位图工厂
public class BitmapImageHttpFactory : IHttpGet<BitmapImage>
{
public HttpGetMethodBase<BitmapImage> CreateHttpRequest()
{
return new HttpGetBitmapImage();
}
}
客户端调用:
客户端调用还是得知道具体的工厂型号,所以这里我打个问号,先看看代码吧
IHttpGet<string> factory = new StringHttpFactory();//string 工厂
factory.CreateHttpRequest().Get("http://douban.fm/j/mine/playlist?from=mainsite&channel=0&kbps=128&type=n").Subscribe(
(result) =>
{
});
代码new了一个具体的工厂,这里并没有达到真正的解耦,所以我考虑看能不能以后做
1。配置文件反射处理
2.依赖注入。
//to be continued................
二.职责链
先看看背景。
虽然用Newtonsoft的json库很爽,但是面对复杂的json串,不能很好的面对它的变化,变化点在于,JToken[][][][][][][][][],中括号的个数未知,我不知道哪天出来的json串会有几个[],如果使用到解析json串的地方很多,这个中括号的数量会非常多,看着非常恶心。。。。。。。。当然也许Newtonsoft有解决办法,但是我没摸索出来。
1.Json串的多样性
json串是由Web服务端安排的,各种命名,各种key/vaule,客户端很难应对这种变。
用职责链的效果是:客户端只用发出获得的json字符串,就可以获得与之对应的类,至于json串怎么被处理的,客户端不知道
上代码
public abstract class RequestorBase<T>
{
protected RequestorBase<T> Successor;
internal void SetSucessor(RequestorBase<T> suc)
{
Successor = suc;
}
public abstract T ProcessRequest(string json);//抽象不依赖于具体,抽象依赖于抽象
} public class Requestor1<T> : RequestorBase<T>
{
public override T ProcessRequest(string json)
{
try
{
return JsonConvert.DeserializeObject<T>(JToken.Parse(json)["song"].ToString());
}
catch
{
Debug.WriteLine("这个是在职责链中的该有的异常");
return Successor.ProcessRequest(json);
}
}
}
public class Requestor2<T> : RequestorBase<T>
{
public override T ProcessRequest(string json)
{
try
{
return JsonConvert.DeserializeObject<T>(JToken.Parse(json)["song"][].ToString());
}
catch
{
Debug.WriteLine("这个是在职责链中的该有的异常");
return Successor.ProcessRequest(json);
}
}
}
public class Requestor3<T> : RequestorBase<T>
{
public override T ProcessRequest(string json)
{
Debug.WriteLine("在职责链中没有能找到处理请求的方法,返回Default");
return default(T);
//NO Chain 继续下去了
}
}
不同的职责人作不同的json串解析。
然后再使用
三.单例模式
使用单例模式来创建管理职责链,使用单例管理职责链的目的是职责链只负责处理json串,他们都是无状态的,所有把他们的方法装入内存就可以了。
public class ManagerResponsibilityChain<T>
{
static private RequestorBase<T> _startrequestor;
static public RequestorBase<T> Instance_Startrequestor
{
get
{
if (_startrequestor == null)
{
Inital();
}
return _startrequestor;
}
}
private ManagerResponsibilityChain()
{ }
static private void Inital()
{
_startrequestor = new Requestor1<T>();
var secondrequestor = new Requestor2<T>();
var thridrequestor = new Requestor3<T>();
_startrequestor.SetSucessor(secondrequestor);
secondrequestor.SetSucessor(thridrequestor);//requestor3 is the end
}
}
今天就到这。
后面再来追加一下:
对于上面的职责链,要想增加职责者,难免会忘记增加的过程,要插入在倒数第二个地方,再重新设置后两个的职责链
public class ManagerResponsibilityChain<T>
{
static private RequestorBase<T> _startrequestor;
static public RequestorBase<T> Instance_Startrequestor
{
get
{
if (_startrequestor == null)
{
Inital();
}
return _startrequestor;
}
}
private ManagerResponsibilityChain()
{ }
static public List<RequestorBase<T>> RequestList=new List<RequestorBase<T>>();
static private void InsertARequestor(RequestorBase<T> InsertItem)
{
RequestList.Insert(RequestList.Count - , InsertItem);
InsertItem.SetSucessor(RequestList[RequestList.Count - ]);
RequestList[RequestList.Count - ].SetSucessor(InsertItem); } static private void Inital()
{ _startrequestor = new Requestor1<T>();
var secondrequestor = new Requestor2<T>();
var thridrequestor = new Requestor3<T>();
RequestList.Add(_startrequestor);
RequestList.Add(secondrequestor);
RequestList.Add(thridrequestor);
_startrequestor.SetSucessor(secondrequestor);
secondrequestor.SetSucessor(thridrequestor);//requestor3 is the end InsertARequestor(new Requestor4<T>());
InsertARequestor(new Requestor5<T>());
InsertARequestor(new Requestor6<T>());
} }
或者是
public class ManagerResponsibilityChain<T>
{
static private RequestorBase<T> _startrequestor;
static public RequestorBase<T> Instance_Startrequestor
{
get
{
if (_startrequestor == null)
{
Inital();
}
return _startrequestor;
}
}
private ManagerResponsibilityChain()
{ } static private void InsertARequestor(RequestorBase<T> InsertItem, List<RequestorBase<T>> RequestList)
{
RequestList.Insert(RequestList.Count - , InsertItem);
InsertItem.SetSucessor(RequestList[RequestList.Count - ]);
RequestList[RequestList.Count - ].SetSucessor(InsertItem); } static private void Inital()
{
List<RequestorBase<T>> RequestList = new List<RequestorBase<T>>();
_startrequestor = new Requestor1<T>();
var secondrequestor = new Requestor2<T>();
var thridrequestor = new Requestor3<T>();
RequestList.Add(_startrequestor);
RequestList.Add(secondrequestor);
RequestList.Add(thridrequestor);
_startrequestor.SetSucessor(secondrequestor);
secondrequestor.SetSucessor(thridrequestor);//requestor3 is the end InsertARequestor(new Requestor4<T>(), RequestList);
InsertARequestor(new Requestor5<T>(), RequestList);
InsertARequestor(new Requestor6<T>(), RequestList);
} }
DoubanFm之设计模式(一)的更多相关文章
- MVVM设计模式和WPF中的实现(四)事件绑定
MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
- java EE设计模式简介
1.何为设计模式 设计模式提供了对常见应用设计问题的解决方案.在面向对象的编程中,设计模式通常在解决与对象创建和交互相关的问题,而非整体软件架构所面对的大规模问题,它们以样板代码的形式提供了通用的解决 ...
- 计算机程序的思维逻辑 (54) - 剖析Collections - 设计模式
上节我们提到,类Collections中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了第一类,本节我们介绍第二类. 第二类方法大概可以分为两组: 接受其他 ...
- 《JavaScript设计模式 张》整理
最近在研读另外一本关于设计模式的书<JavaScript设计模式>,这本书中描述了更多的设计模式. 一.创建型设计模式 包括简单工厂.工厂方法.抽象工厂.建造者.原型和单例模式. 1)简单 ...
- 《JavaScript设计模式与开发实践》整理
最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...
- 设计模式之行为类模式大PK
行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...
- .NET设计模式访问者模式
一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...
- Java开发中的23种设计模式详解
[放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...
- java 设计模式
目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计 ...
随机推荐
- IBM Appscan基本操作手册
一.操作前提 1.首先下载Appscan的安装包 2.安装Appscan 二.操作流程 1.双击图标,打开Appscan软件 2.打开软件后,页面显示如下: 3.选择“文件-新建”,弹出如下的窗口: ...
- 解决error C2059: 语法错误:“::”问题
错误代码提示: >f:\opencv\opencv\build\include\opencv2\flann\lsh_table.h(): error C2059: 语法错误:“::”f:\ope ...
- 有关OpenCV1.0中GUI命令的几个函数学习总结
1.修改窗口背景色或者光标形状 在OpenCV1.0版本利用函数int cvNamedWindow( const char* name, int flags )初始化创建一个窗口后,窗口的背景色是灰色 ...
- oracle数据库中的表设置主键自增
oracle中没有自增字段,可通过序列+触发器间接实现,cmd中sqlplus登录,直接运行即可.一般要经过一下几步: 1建立数据表 create table Test_Increase( ...
- centos6.5没有eth0, 只有eth1, eth1无法上网
1. cat /etc/udev/rules.d/70-persistent-net/rules 2.将ATTR(address)=XXXXXXXX的内容 替换 文件/etc/sysconfig/ ...
- 二模09day2解题报告
T1.domino骨牌 n张有黑有白的骨牌排一排,连续三张同色排一起就不好看,求共多少方案不好看. 分析一下,f[3]=2,f[4]=6,f[n]:如果n-1==n 那么方案数为f[n-2],如果不同 ...
- oracle中行转列、列转行函数
多行转字符串 这个比较简单,用||或concat函数可以实现 select concat(id,username) str from app_user select id||username str ...
- Mongodb解决不能连接到服务器的错误
注:这次解决的这个问题的前提是之前打开MongoDB之后,再次使用的时候无法连接了(使用mongod和mongo都不对) 闲话:遇到这种问题真是让人恼火,所以说句sun of beach,好了~爽 正 ...
- SVN 忽略获取和提交obj、bin文件夹
一.全局设置的方式(貌似不行) SVN忽略文件夹刚开始用的是这种方式: Settings => Subversion里的Global ignore pattern增加这两项*/bin */obj ...
- leetcode 36
36. Valid Sudoku Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudok ...