分类 Coding 下的文章

设计模式:Mediator

针对问题

面向对象设计鼓励将行为分布到各个对象中。这种分布可能会导致对象间有许多连接。在最坏的情况下,每一个对象都知道其它所有对象。
而系统设计中,这种相互连接会增加对象间的耦合度,系统将逐渐成为一个难以分割的整体,以至于对系统系统无法进行大的改动。
Mediator模式的作用便是分离“对象”与“对象之间的交互”逻辑。

介绍

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

实现

Mediator模式的静态图如下:

其中:
Mediator定义一个用于与各对象通信的接口(当仅有一个ConcreteMediator时可以不定义Mediator接口)。
ConcreteMediator实现具体通信逻辑并维护通信对象列表。
ConcreteColleague保存Mediator对象的引用,在需要与其他对象通信时,改为与Mediator通信。… Read the rest

设计模式:Iterator

针对问题

如果要遍历一个列表,可以为列表类型声明first/next/end等函数,并在其中封装具体的遍历逻辑。但是这么做有几个弊端:
1、如果需要以不同的实现方式遍历列表,那么可能需要声明多种遍历操作。
2、一个列表可能需要同时进行多个遍历。
解决的方法之一就是把遍历相关的操作提取到另一个类中,这就是Iterator模式。

介绍

提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。

实现

Iterator模式的静态图如下:

图中:
Aggregate为被访问对象的基类,它声明一个获取Iterator的函数。
ConcreteAggregate返回的ConcreteIterator实例,在ConcreteIterator中实现具体的迭代操作。

Iterator模式的实现要注意以下几点:
1、Iterator可分为内部和外部两种,外部Iterator由客户控制每一步遍历,内部Iterator只需要提交一个待执行的操作,Iterator负责对每一个元素执行该操作。… Read the rest

设计模式:Command

针对问题

假设要设计一个文本编辑器的“打开”按钮,点击之后显示“打开”对话框,之后在窗口中显示文档的内容。我们可以通过按钮类派生一个新类,重写Click处理
逻辑,在Click函数中执行以上的功能。
但这样设计的问题有两个:
1、如果需要多个按钮,那么每种按钮都需要派生一个新类。
2、如果要实现一个“打开”的菜单项,由于菜单不能继承自按钮,代码无法复用。
在这种情况下需要用某种设计模式将“调用者”与“算法逻辑”、“被操作者”解耦。

介绍

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

实现

Command模式的静态图如下:

其中:
Invoker为操作的调用者,例子中的“打开”按钮。
Receiver为被操作对象,例子中的文档窗口。… Read the rest

设计模式:Chain Of Responsibility

针对问题

在看电视新闻的时候经常会有这种情况:某一个记者去采访某部门,接待人员告诉他“这件事我处理不了,得找领导”
领导告诉他:“这件事不归我们管,得找xx部”,然后把电话转到xx部。
xx部的接待告诉他:“这件事我们也没辙,得找yy部”,然后把电话转到yy部。
在这种情况下,每一个部门都有可能处理这件事,但是记者也并不知道最终谁会出面处理,也不知道能不能处理。
把记着比作调用者,把接电话的每个人比作处理类,就形成了责任链模式。

介绍

为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

实现

责任链模式的静态图如下:

每一个潜在的调用处理者都需要继承Handler类。Handler类需要做两件事情:
1、声明HandleRequest方法。… Read the rest

为什么Lisp语言如此先进?

为什么Lisp语言如此先进?

作者:Paul Graham

译者:阮一峰

英文原文:Revenge of the Nerds

(节选自即将出版的《黑客与画家》中译本)

一、

如果我们把流行的编程语言,以这样的顺序排列:Java、Perl、Python、Ruby。你会发现,排在越后面的语言,越像Lisp。

Python模仿Lisp,甚至把许多Lisp黑客认为属于设计错误的功能,也一起模仿了。至于Ruby,如果回到1975年,你声称它是一种Lisp方言,没有人会反对。

编程语言现在的发展,不过刚刚赶上1958年Lisp语言的水平。

二、

1958年,John McCarthy设计了Lisp语言。我认为,当前最新潮的编程语言,只是实现了他在1958年的设想而已。

这怎么可能呢?计算机技术的发展,不是日新月异吗?1958年的技术,怎么可能超过今天的水平呢?

让我告诉你原因。

这是因为John McCarthy本来没打算把Lisp设计成编程语言,至少不是我们现在意义上的编程语言。他的原意只是想做一种理论演算,用更简洁的方式定义图灵机。… Read the rest

设计模式:Flyweight

针对问题

当系统中有大量相似对象时,例如一个文本处理程序中的字符,假如用对象来保存每个字符,两个'a'字符对象的字符是相同的,只有位置、颜色、大小等区别,如果为每个字符保存所有信息的话,那么程序占用内存将会十分庞大。Flyweight模式将不同对象直接共享的信息抽取为一个共享对象以节约系统资源。

介绍

运用共享机制有效的支持大量细密度的对象。

实现

Flyweight模式的静态图如下:

其中:
Flyweight类描述了一个操作接口,这个接口接受并作用于外部状态。
ConcerteFlyweight类实现Flyweight接口,并保存内部状态,内部状态是与调用场景无关的,所以它可以在多个调用场景之间被共享。
UnsharedConcreteFlyweight类同样实现Flyweight接口,但它保存的状态并不独立于调用场景,也就是说它可以是非共享的。
FlyweightFactory类管理Flyweight的创建并可以实现引用计数和垃圾回收,这意味着需要屏蔽Flyweight的构造函数。… Read the rest

设计模式:Facade

针对问题

假设多个相互关联的类组成了一个子系统,其他系统在使用这个系统功能的时候必须知道这些类的功能,这无疑加大了使用难度。Facade模式为外部提供了一个统一的调用接口,系统外部想要使用子系统功能时不再需要了解各类型的细节,这类似于面向对象中接口与实现的关系。

介绍

为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

实现

Facade模式的实现比较简单,如下图:

Facade需要为客户提供完整的接口,客户在使用子系统时可以不必直接访问子系统中的其他对象。

特点

1、使用Facade模式可以降低子系统的使用难度,并降低系统间的耦合度。
2、调用方如果了解子系统的实现方式也可以跳过Facade,直接使用具体业务对象。

相关文章

设计模式总结

参考文章

  1. 《设计模式_可复用面向对象软件的基础》,
Read the rest

设计模式:Decorator

针对问题

有时我们希望给某个类增加一些功能。这时有两个选择:
1、继承这个类并实现一个派生类,在派生类中编写新的功能逻辑,这样做的主要问题是一个功能就需要对应一个派生类,多层继承时类的数量会成倍增长。
2、使用对象的组合,将新的功能委托给别的对象实现,并提供一致的调用接口。Decorator模式便是这种思路的一个实现方式。

介绍

动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。

实现

Decorator模式的静态图如下:

Decorator模式维护一个单路的层级关系,Decorator与Component需要有共同的接口。可以认为是一个新的Decorator“包裹”了旧的对象,在将调用转发给旧对象后实现Decorator自己的逻辑功能,如下图:

可以看出Decorator模式与Composite模式的实现方式非常相似,这两种模式的主要区别是Decorator模式只需要维护一个component节点,这也体现了这两种模式的区别:Composite模式侧重于对象结构的维护,Decorator模式侧重于转发请求时增加其他功能。… Read the rest

设计模式:Composite

针对问题

一般的GUI框架都会有“容器”和“控件”的概念,一个容器可以包含多个控件,一个容器也可以包含其他容器;控件可以包含子控件,几个控件组合到容器里可以作为新的控件。如果代码实现中单独处理“容器”和“控件”的绘制的话将会十分复杂,如果用递归的方式去思考这个问题,那么问题可以简化成:

这就是Composite模式。

介绍

将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。

实现

Composite模式的UML图如下:

Composite是典型的树形结构,如下图:

其中:
1、Leaf节点没有子节点
2、Component节点的Operation被调用时,除了自身的操作(可以空操作),它还会将请求转发给子节点。… Read the rest

设计模式:Proxy

针对问题

假如说我需要对某个类型的调用做一些控制,例如载入一副图片的步骤可以分为三步:

假如说load这一步需要的时间很长,而draw不一定在什么时候调用(比如word文档中的图片要浏览到图片位置时才显示),那么自然会考虑可以在不改变程序结构的前提下把load这一步推迟到draw调用,以节约初始化的时间。这种情况适合于Proxy模式。

介绍

为其他对象提供一种代理以控制对这个对象的访问。
Proxy模式可以分为以下4类:
1、远程代理:为一个对象在不同的地址空间提供局部代表。
2、虚代理:延迟加载大对象。
3、保护代理:控制对原始对象的访问。
4、智能引用:引用计数、单例、锁等。

实现

Proxy模式的静态图如下:

其中:
1、Proxy需要提供与Subject相同的接口。
2、C++中可以重载->操作符以实现对RealSubject的访问,例如:… Read the rest

分类目录