前两版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. kubernetes源码解析---- apiserver路由构建解析(1)

    kubernetes源码解析---- apiserver路由构建解析(1) apiserver作为k8s集群的唯一入口,内部主要实现了两个功能,一个是请求的路由和处理,简单说就是监听一个端口,把接收到 ...

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

    来源 http://www.imooc.com/code/1315 所谓优先级,就是在表达式中的运算顺序.Java 中常用的运算符的优先级如下表所示: 级别为 1 的优先级最高,级别 11 的优先级最 ...

  3. python列表的常用操作方法

    主要介绍了Python中列表(List)的详解操作方法,包含创建.访问.更新.删除.其它操作等,需要的朋友可以参考下. 1.创建列表.只要把逗号分隔的不同的数据项使用方括号括起来即可 List = [ ...

  4. 改变ListCtrl某行的背景色或者字体颜色

    大家也许熟悉WM_NOTIFY,控件通过WM_NOTIFY向父窗口发送消息.在WM_NOTIFY消息体中,部分控件会发送NM_CUSTOMDRAW告诉父窗口自己需要绘图. 也可以反射NM_CUSTOM ...

  5. css自定义字体完美解决方案example

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 雷兽的数据库CAP乱谈之(一)阐述

    今天有人问我cap,找了https://my.oschina.net/lilw/blog/169776这片文字, 下面是cap那篇文字的解释: 所谓CAP理论,即: Cosistency       ...

  7. WP8__从windowsphone app store 中根据app id获取应用的相关信息(下载网址及图片id等)

    windows phone 官网应用商店地址 http://www.windowsphone.com/zh-cn/store/featured-apps------------------------ ...

  8. Java druid

    1.ConnectionFactory (添加引用:druid-1.0.1.jar) package nankang.test; import java.sql.Connection; import ...

  9. 配置DNS域名解析服务器

    bind这个DNS域名解析服务器解析好后,执行下面的语句实现开启服务 named -c named.conf & -c指配置脚本named.conf的文件地址 named.conf主要有下面几 ...

  10. 使用BootStrap制作用户登录UI

    先看看劳动成果 布局 左右各一半(col-md-6) 左侧登录框占左侧一半的10/12 右侧是登录系统的注意事项 使用到的BootStrap元素 well 输入框组(input-group) 按钮(b ...