最近又在首页看到几篇设计模式相关的学习随笔。回想起来,这几年在园子里发布的有关设计模式的随笔都有一个共同的特点。那就是Factory和Singleton居多,如果是系列的,也往往是从这两个模式开始的。由于能够坚持把《设计模式》中所有模式都写完的非常少,所以基本上也很少见到有关其它模式的随笔。

这种情况也很好理解,因为《设计模式》这本书就是按照这个顺序来的。最先讲述的就是Abstract Factory模式,于是它排第一也无可厚非;排第二的Builder基本不太容易见到;第三的Factory Method由于也叫“Factory”所以往往和Abstract Factory放在一起,或者干脆就混淆了; 第四的Prototype也不是太容易见到;第五位的Singleton简单易懂,易学易用。而再往后的模式,恐怕作者们就没什么耐心学下去了……这可能就是为什么Factory和Singleton出现频率如此之多的原因吧。

《设计模式》已经出版超过15年了,到今天已经不是什么新鲜的东西了,可以说正在由“绝招”慢慢向着“基本功”转变着。然而,这种学习模式的方式方法却实在令人担忧。

Abstract Factory在实际中并不常见,因为它需要你有两套并行的继承体系,需要对同一个抽象有多于一种的实现方式。这种复杂的系统可以说不是每个领域,每个开发人员都能遇到的。在某些特定的领域可能很常见,但是在大多数领域并不需要这么复杂的对象创建方法。这就造成了很多人“杀鸡用宰牛刀”,用复杂的方式,解决不那么复杂的问题。后果是增加了不必要的复杂度,给系统维护增加了困难。

另一个模式Singleton,由于实现简单,意图“似乎”也很明显。被很多人用来作为“优化”的一种方式。通过这种方式来节省内存空间,减少对象实例。但是单一实例本身就等同于全局变量,而全局变量在几十年前就已经被证明是“反模式”了,用另一种形态的全局变量来代替另一种形态的全局变量有什么好处么?问题在与,Singleton的“意图”并不在于优化,而是在于“妥协”。Singleton的目的在于保证对象有单一的实例,这是因为对象必须要有单一的实例,如果存在多个实例,可能会引发错误。也就是说,Singleton以牺牲程序的清晰和可维护性,来达到保证程序正确的目的。这跟本就和优化八竿子打不着,这完全是一种设计上的妥协,牺牲一些好处来获取更大的好处。如果仅仅是为了节省几个对象实例,而非程序的正确才使用Singleton,那就是丢了西瓜拣芝麻。况且节省那几个实例也跟本就不可能对程序的性能有太大的影响(特殊领域除外)。

人的时间是有限的,23个模式也不是都那么常用,哪些模式才是最经常用到的,才是最值得学习的呢?

第一梯队:Iterator,Observer,Template Method,Strategy

Iterator:LINQ,foreach这不都是Iterator么。

Observer:MVC的核心,.NET中事件就是Observer。

Strategy:对同一个行为有不同实现的时候,如果考虑将行为的实现委托(不是.NET中的委托)给另一个类,那就用到了Strategy。通过这种方式,可以简单的替换算法的实现类,来达到更换算法的目的。

代码

class Foo
{
  private IBar bar;
  public Foo(IBar bar)
  {
    this.bar = bar;
  }

public void DoSomething()
  {
    //some code
    bar.DoWhatYouWant();
    //some code
  }
}

class A : IBar
{
  public void DoWhatYouWant()
  {
    //do in A's way
  }
}
class B : IBar
{
  public void DoWhatYouWant()
  {
    //do in B's way
  }
}

Template Method:一个算法的同一个步骤有不同的实现,通过继承来实现。这种方式通过创建子类来改变算法的实现和行为。ASP.NET WebForm中Page的OnInit,OnLoad等事件,就是Template Method

代码

class Foo
{
  public void DoSomething()
  {
    //some code
    DoWhatYouWant();
    //some code
  }
  protected abstract void DoWhatYouWant();
}

class A: Foo
{
  protected override void DoWhatYouWant();
  {
    //do in A's way
  }
}

class B: Foo
{
  protected override void DoWhatYouWant();
  {
    //do in B's way
  }
}

面向对象的一个重要特点就是多态,也就是对于同一个动作有不同的行为。Strategry通过委托的方式,将一个算法的不同实现委托给其它类;Template Method通过继承的方式,让子类实现算法的可变部分,基类则处理算法的流程和不变部分。近年来组合优于继承的观点已经成为主流,因此Strategy的处境频率相对高一些,但是Template Method在解决简单问题的时候更好用,只要注意继承层次不要太多(<=3)就好。

第二梯队:Adapter,Facade,Decorator

Adapter:当你需要使用第三方库,但是又不想太依赖于它的API,以便于今后在需要时可以方便的切换到另一个库的时候,你就需要在你的代码和第三方API之间放置一个抽象层,也就需要用Adapter模式了。比如你想使用log4net,如果直接在代码中到处引用log4net的API,将来有一天需要切换到另一个库比如EntLib,你的改动量可就大了去了。如果在一开始就自己设计一个API,在代码中使用自己的API,再用Adapter模式将log4net的API包装到自己的API中,如果有一天想要切换到Entlib,只要为EntLib在写一个Adapter就行了。对于IoC框架也是一样的。不过需要注意的是,如果第三方库的API接口非常庞大,使用Adapter就会很麻烦,因为你需要包装太多的东西,那么使用Adapter可能就不是一个太好的主意。或许谨慎考虑确定一个不太可能会变化的第三方库更好一些。

Facade:基本上用于简化API,隐藏细节,在一个系统中,高层模块调用低层模块时,如果低层模块API比较复杂,而高层模块并不需要这种复杂度,那么加一个Facade,可以简化高层模块使用API的难度。

Decorator:为一个类的行为增加行为,比如ASP.NET MVC中的Action Filter。

第三梯队:Command,State,Composite

Command:统一接口,Undo/Redo。

State:当你的model有多种状态,model的行为在每种状态下并不一样的时候,就需要用State。如果你有多个相似的Switch,那也可能意味着需要用State来代替Switch。

Composite:ASP.NET WebForm的Page和Control就是一个例子。

这些模式和分类只是凭我的感觉,并没有任何实际的数据做支持,而我的感觉也只来源于我所接触到的领域和代码。 希望同学们也可以提供自己接触到的代码中,最常见到和用到的模式。

哪些设计模式最值得学习相关推荐

  1. 值得学习的C/C++开源框架(转)

    值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的 ...

  2. 值得学习的C语言开源项目

    值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的 ...

  3. CoffeeScript不是一门值得学习的语言

    译注:看到这篇文章时发现不论在国内还是国外的网站上都有很多人在争论,很有意思.不过令人汗颜的是有些同学似乎只看了标题就开始吵了起来,完全没理解作者的真正意图.如果有兴趣,请耐心看完. ======= ...

  4. 值得学习的C++开源项目(转)

    值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的 ...

  5. C/C++开源项目资源,值得学习。

    C/C++开源项目资源~ 值得学习的C语言开源项目 - 1. Webbench Webbench是一个在Linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的UR ...

  6. 2020 年最值得学习的 5 大 AI 编程语言

    来源:学术头条 本文约1571字,建议阅读4分钟. 本文介绍2020 年最值得学习的 5 大 AI 编程语言,希望对想学习人工智能的读者有帮助. 人工智能是当今世界最具需求的一个领域,人工智能通过编程 ...

  7. 2015年最值得学习的编程语言是?

     2015年最值得学习的编程语言是? 2015-03-04 10:31 来源:优才网 编辑:Loading[纠错]12人评论 A-A+ 怎么开淘宝店 网站优化方法 创业如何获得投资 小米note顶 ...

  8. 2021年,Java开发者值得学习的13项技能

    本文分享自百度开发者中心2021年,Java开发者值得学习的13项技能 作者 | Olivia Cuthbert 译者 | 王强 策划 | 刘燕 如果你想在这个竞争激烈的世界里,成为一名熟练开发 Ja ...

  9. Github 上 10 个值得学习的 Springboot 开源项目

    Spring Boot 几乎继承了所有 Spring 框架的优点,同时还可以让项目的配置更简化.编码更简化.部署更方便.近两年受到很多开发者的追捧,也是火热的不行! 下面给大家整理了 10 个 Git ...

最新文章

  1. 关于navicat连接oracle 报 ORA-12737 set CHS16GBK错误的解决方法
  2. hexo的yilia主题鼠标点击出现小红心
  3. aliddns ipv6_群晖使用阿里云DDNS(ipv4和ipv6)
  4. Expression Bland 入门视频(五) 了解对象面板和属性面板
  5. cocos2d-x初探学习笔记(6)--场景间切换效果
  6. Tengine-Ngnix高级版
  7. python 电脑显示桌面_使用Python快速实现显示器关闭和锁住桌面
  8. 《大数据》2015年第3期“网络大数据专题”——大数据时代的互联网分析引擎...
  9. python色标_Python: 气象绘图实例之台风
  10. java list移除符合条件的元素_从List中移除指定 List 中包含的其所有元素(可选操作)。...
  11. 旧版eclipse安装maven_厉害!Eclipse 已经开始可以支持 Java 14~
  12. Android内容提供者(读取手机联系人信息)
  13. 拦截导弹问题(递归)
  14. Choco使用小记--如何设置choco的默认软件包安装位置
  15. 30分钟快速了解云计算
  16. 地理信息科学期末考试重要知识点总结
  17. 基于Android的高德地图的定位和运动轨迹记录的功能
  18. 设计原则 - 单一职责原则
  19. 实现字符串左旋和右旋的常见方法
  20. 苹果手机防盗软件_魅族手机防盗拍照功能可以成功定位,比其他的防盗软件好用...

热门文章

  1. java与sql2005连接数据库_Java链接数据库SQl Server2005
  2. rust加载不进去服务器eac_基于腾讯云的 Rust 和 WebAssembly 函数即服务
  3. Java 字节和字符流的读写+Buffered
  4. Linux监控工具介绍系列——smem
  5. xv6/调度算法及并发程序设计
  6. Three.js基础探寻二——正交投影照相机
  7. KingPaper初探ThinkPHP3.1.2之目录部署(二)
  8. ASP.NET 错误
  9. SQL Server 兼容模式
  10. [Leedcode][JAVA][第125题][验证回文串][双指针][String]