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):迪米特法则 设计 ...
随机推荐
- Android WebView Long Press长按保存图片到手机
<span style="font-size:18px;">首先要先注册长按监听菜单 private String imgurl = ""; /** ...
- android NDk环境编译总结
首先,这篇文章的撰写是基于很多前人的优秀的帖子,感谢他们的分享让我能够学习这么多的知识.谢谢 Android NDK开发环境的搭建 前言: Android 上,应用程序的开发,大部分基于 Java 语 ...
- 初探接口测试框架--python系列5
点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是 ...
- Photoshop Cs5 64位系统破解版下载(内含破解方法)
Photoshop Cs5 64位系统是电影.视频和多媒体领域的专业人士, 使用 3D 和动画的图形和 Web 设计人员, 以及工程和科学领域的专业人士的理想选择,下面提供Photoshop Cs5 ...
- UGUI不规则按钮实现思路
根据图片的透明度来判断是否点击到了适当区域(如果a值是0,说明完全透明,则判断为没点击,否则判断为触发点击) using UnityEngine; using System.Collections; ...
- Objective-C的内存管理
一.Objective-C内存管理的对象 1. 值类型:比如int.float.struct等基本数据类型. 值类型会被放入栈中,在内存中占有一块连续的内存空间,遵循先进后出的原则,故不会产生碎片. ...
- 百度校招面试经历及总结(已发offer)
听说发面经可以攒rp,希望早点给我确定的offer通知,也希望看到这个面经的小伙伴能顺利拿到心仪的offer~ 职位:机器学习-数据挖掘工程师 9.15 上午11点 一面 1.介绍项目 2.考研意向, ...
- 实验室中搭建Spark集群和PyCUDA开发环境
1.安装CUDA 1.1安装前工作 1.1.1选取实验器材 实验中的每台计算机均装有双系统.选择其中一台计算机作为master节点,配置有GeForce GTX 650显卡,拥有384个CUDA核心. ...
- 洛谷P1983 车站分级
P1983 车站分级 297通过 1.1K提交 题目提供者该用户不存在 标签图论贪心NOIp普及组2013 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 求帮忙指出问题! 我这么和(diao ...
- 利用Ossim系统进行主机漏洞扫描
利用Ossim系统进行主机漏洞扫描 企业中查找漏洞要付出很大的努力,不能简单的在服务器上安装一个漏洞扫描软件那么简单,那样起不了多大作用.这并不是因为企业中拥有大量服务器和主机设备,这些服务器和设备又 ...