前两版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之设计模式(一)的更多相关文章

  1. MVVM设计模式和WPF中的实现(四)事件绑定

    MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  2. java EE设计模式简介

    1.何为设计模式 设计模式提供了对常见应用设计问题的解决方案.在面向对象的编程中,设计模式通常在解决与对象创建和交互相关的问题,而非整体软件架构所面对的大规模问题,它们以样板代码的形式提供了通用的解决 ...

  3. 计算机程序的思维逻辑 (54) - 剖析Collections - 设计模式

    上节我们提到,类Collections中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了第一类,本节我们介绍第二类. 第二类方法大概可以分为两组: 接受其他 ...

  4. 《JavaScript设计模式 张》整理

    最近在研读另外一本关于设计模式的书<JavaScript设计模式>,这本书中描述了更多的设计模式. 一.创建型设计模式 包括简单工厂.工厂方法.抽象工厂.建造者.原型和单例模式. 1)简单 ...

  5. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  6. 设计模式之行为类模式大PK

                                        行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...

  7. .NET设计模式访问者模式

    一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...

  8. Java开发中的23种设计模式详解

    [放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...

  9. java 设计模式

    目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计 ...

随机推荐

  1. Unity3D 新人学习的一点感想

    想到那里写到那里吧 1.Unity3D的优点大家都知道:组件化.c#语言.可见即所得. 当初刚开始学习的是cocos2dx,c++的货,觉得还是写的不错的,也是国人开发的,真的代码很容易懂,直接看引擎 ...

  2. 慕课网-安卓工程师初养成-3-2 Java中的算术运算符

    来源:http://www.imooc.com/code/1279 算术运算符主要用于进行基本的算术运算,如加法.减法.乘法.除法等. Java 中常用的算术运算符: 其中,++ 和 -- 既可以出现 ...

  3. 让Windows7运行速度更快的BIOS优化设置教程

    和以前使用WindowsXP一样,很多用户都在设法提高windows7的系统运行速速,比较常见的方法大多是对系统服务进行优化,去掉一些可有可无的系统服务,还有就是优化资源管理器菜单等.除此之外,还有一 ...

  4. QTP动态加载对象库

    Public Function AddObjectRepository(path) On Error Resume Next Dim pos, repath If instr(path,". ...

  5. 启动obiee

    启动obiee:1.启动数据库第一步:打开Oracle监听$ lsnrctl start第二步:使用sysdab角色登录sqlplussqlplus / as sysdba第三步:启动数据库SQL&g ...

  6. UVa11054 Gergovia的酒交易 Wine trading in Gergovia-递推

    https://vjudge.net/problem/UVA-11054 As you may know from the comic “Asterix and the Chieftain’s Shi ...

  7. 华为OJ平台——整形数组合并

    题目描述: 将两个整型数组按照升序合并,并且过滤掉重复数组元素 输入: 输入说明,按下列顺序输入: 1 输入第一个数组的个数 2 输入第一个数组的数值 3 输入第二个数组的个数 4 输入第二个数组的数 ...

  8. android反编译工具总结

    序:总结反编译主要的目的在于学习.利用反编译进行相关的汉化或修改,都是不道德的! 大家都知道,将apk文件解压后有两部分文件需要处理,一种是xml文件,另一种一个dex文件(.dex),我们可以从.d ...

  9. js的二元三元操作符

    二元 if ( a == b) { alert(a) } // (a == b) && alert(a) if ( a != b) { alert(a) } // (a == b) | ...

  10. python urllib urllib2

    区别 1) urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL.这意味着,用urllib时不可以伪装User Agent字符串等. 2) u ...