Proxy Pattern属于Structural Patterns
介绍:
Proxy Pattern的作用是为其他对象提供一个代理以控制对这个对象的访问,如何你的对象创建非常昂贵;需要访问控制;是一个远程对象或者调用之前需要采取一些其他操作,那么你可以考虑为该对象创建一个代理。
设计于实现:
ISubject:一个公共的接口供代理和被代理对象继承
Subject:需要被代理的对象
Proxy:代理对象 A class that creates, controls, enhances, and authenticates access to a Subject
public interface ISubject { string Request(); } public class Subject : ISubject { #region ISubject Members public string Request() { return "Subject Request "; } #endregion } public class Proxy : ISubject { Subject subject; public string Request() { if (subject == null) { Console.WriteLine("Subject inactive"); subject = new Subject(); } Console.WriteLine("Subject active"); return "Proxy: Call to " + subject.Request(); } } public class ProtectionProxy : ISubject { // An authentication proxy first asks for a password Subject subject; string password = "Abracadabra"; public string Authenticate(string supplied) { if (supplied != password) { return "Protection Proxy: No access"; } subject = new Subject(); return "Protection Proxy: Authenticated"; } public string Request() { if (subject == null) { return "Protection Proxy: Authenticate first"; } return "Protection Proxy: Call to " + subject.Request(); } } [TestFixture] public class ProxyPatternTest { [Test] public void T1() { ISubject subject = new Proxy(); Console.WriteLine(subject.Request()); ISubject subject2 = new ProtectionProxy(); Console.WriteLine(subject2.Request()); Console.WriteLine((subject2 as ProtectionProxy).Authenticate("Abracadabra")); Console.WriteLine(subject2.Request()); } }
Decorator Pattern 和 Proxy Pattern 的区别:
Decorator Pattern 有"Smart Proxy" 可见两者有相同之处,在Decorator Pattern中装饰者和被装饰者都实现了相同的接口,这个Proxy Pattern一样代理和被代理的对象也同样实现了相同的接口。同时装饰者和代理都可以对实际的对象进行控制。
但是两者最显著的区别是Proxy Pattern是在代理类内部创建对象的实例,而Decorator Pattern是通过参数传递对象的实例。
var component = new Component();
//Component是通过构造函数的方式传递给DecoratorB的
var decoratorB = new DecoratorB(component);
public class Proxy : ISubject
{
Subject subject;
public string Request()
{
if (subject == null)
{
Console.WriteLine("Subject inactive");
//在代理的内部创建类(Subject)的实例
subject = new Subject();
}
…
}
}
参考文章:
1、The differences between Decorator Pattern and Proxy Pattern
2、How do the Proxy, Decorator, Adaptor, and Bridge Patterns differ?
Decorator Pattern属于Structural Patterns
介绍:
Decorator pattern的作用是提供一种方式动态的给一个对象添加新的职责或状态,被装饰的对象并不知道被“装饰”了。A key implementation point in the Decorator pattern is that decorators both inherit the original class and contain an instantiation of it.
实现:
UML 类图
public interface IComponent { string Operation(); } /// <summary> /// 被装饰者 /// </summary> public class Component : IComponent { #region IComponent Members public string Operation() { return "I'm a photo;"; } #endregion } /// <summary> /// 装饰者A /// </summary> public class DecoratorA : IComponent { IComponent component; public DecoratorA(IComponent component) { this.component = component; } #region IComponent Members public string Operation() { return component.Operation() + "and decorated by DecoratorA"; } #endregion } /// <summary> /// 装饰者B /// </summary> public class DecoratorB : IComponent { IComponent component; public string AddedState = " and added state"; public DecoratorB(IComponent component) { this.component = component; } #region IComponent Members public string Operation() { return component.Operation() + "and decorated by DecoratorB"; } public string AddedBehavior() { return " and added behavior by DecoratorB"; } #endregion } public class Client { public static void Display(string s, IComponent component) { Console.WriteLine(s + component.Operation()); } } [TestFixture] public class DecoratorTest { [Test] public void T1() { var component = new Component(); Client.Display(string.Empty, component); var decoratorB = new DecoratorB(component); Client.Display("hello!", decoratorB); } }
搜索的自动提示功能能给用户带来很好的搜索体验,由于中文的特点,如果搜索自动提示可以支持拼音的话会给用户带来更大的方便,免得切换输入法。目前大多数的电子商务网站都支持拼音提示功能。
关于多音字
由于中文存在多音字问题(读音,声调),例如 调的读音有DIAO;TIAO 长的读音有CHANG;ZHANG 所以对于一个词语如果用程序组合可能有多个组合,比如美的空调有4中组合:meidikongtiao;meidikongdiao; meidekongtiao;meidekongdiao 如何处理这中问题要做到精确第一需要有拼音库还要分词,这种处理难度较大,第二种就是把所有可能组合在一起,这样的缺点是一个词汇组合太多(阶乘);提示结果不准确。
大多数电子商务网站都采用第二种方案:例如 洗衣机 洗字有xian 和xi 两种读音。
淘宝商城:
卓越:
京东:
SQLServer还是MongoDB
如果使用sql server这样的关系型数据库 需要见两张表一张数提示词一张表是对应的读音,这样不管存储还是读取都相对比较麻烦,同时这种查询数次较高(用户每输入一个字符都要查询数据库)对sql server 造成不必要的浪费。
MongoDB是一种非关系型的文档数据库,开源,免费,具有易于使用,效率高等特点,存储是JSON格式,强大的查询功能(数组和正则表达式的支持)。
比如 美的空调 可以存储为 {name:’美的空调’;pinyin:[meidikongtiao’,’meidekongtiao’]}
查选也很方便,例如我们用户输入xian,我们的查选语句就是这样的:
查询结果为:
关于汉字转拼音可参考:
使用Microsoft Visual Studio International Pack获得中文字符串的所有拼音组合(处理多音字)
ASP.NET MVC 中有一个神器Model Binder,给开发带来很多便利,如果使用WebForm 开发的话,只能望洋兴叹了,不过人类是无法阻止程序猿解决问题的决心的。
废话不多说了,直接看看这个山寨版的 "Model Binder"
复杂类型使用示例
先定义几个简单的实体:
public class User
{
public int SysNo { get; set; }
public string Name { get; set; }
public bool Good { get; set; }
public DateTime Birthday { get; set; }
public Address Address { get; set; }
public int[] Test { get; set; }
public List<Order> Orders { get; set; }//不支持复杂列表类型的转换
}
public class Order
{
public string OrderID { get; set; }
}
public class Address
{
public User User { get; set; }
public int SysNo { get; set; }
public string Name { get; set; }
}
然后看看界面上表单的样子
看看效果
转换成功!!
如何判断用户没有输入或者转换失败呢?
很简单在Global中注册默认值
protected void Application_Start(object sender, EventArgs e)
{
RequestBinder.RegistDefaultValue<int>(-999999);
RequestBinder.RegistDefaultValue<DateTime>(DateTime.Parse("1900/01/01"));
}
上面是复杂类型,对于简单的更不在话下了,只要指定表单的Name就可以了
int sysno = RequestBinder.UpdateModel<int>("SysNO");
源码下载:
{
public void ProcessRequest(HttpContext context)
{
OutputCachedPage page = new OutputCachedPage(new OutputCacheParameters
{
Duration = 60,
Location = OutputCacheLocation.Server,
VaryByParam = "v"
});
page.ProcessRequest(HttpContext.Current);
context.Response.Write(DateTime.Now);
}
public bool IsReusable
{
get
{
return false;
}
}
private sealed class OutputCachedPage : Page
{
private OutputCacheParameters _cacheSettings;
public OutputCachedPage(OutputCacheParameters cacheSettings)
{
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
_cacheSettings = cacheSettings;
}
protected override void FrameworkInitialize()
{
// when you put the <%@ OutputCache %> directive on a page, the generated code calls InitOutputCache() from here
base.FrameworkInitialize();
InitOutputCache(_cacheSettings);
}
}
}
/// <summary>
/// method for converting a UNIX timestamp to a regular
/// System.DateTime value (and also to the current local time)
/// </summary>
/// <param name="timestamp">value to be converted</param>
/// <returns>converted DateTime in string format</returns>
private static DateTime ConvertTimestamp(double timestamp)
{
//create a new DateTime value based on the Unix Epoch
DateTime converted = new DateTime(1970, 1, 1, 0, 0, 0, 0);
//add the timestamp to the value
DateTime newDateTime = converted.AddSeconds(timestamp);
//return the value in string format
return newDateTime.ToLocalTime();
}
/// <summary>
/// method for converting a System.DateTime value to a UNIX Timestamp
/// </summary>
/// <param name="value">date to convert</param>
/// <returns></returns>
private double ConvertToTimestamp(DateTime value)
{
//create Timespan by subtracting the value provided from
//the Unix Epoch
TimeSpan span = (value - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime());
//return the total seconds (which is a UNIX timestamp)
return (double)span.TotalSeconds;
}














