From 5ac54ac89f826f1b181f111465def9563c852518 Mon Sep 17 00:00:00 2001 From: me115 Date: Sun, 12 Oct 2014 18:42:45 +0800 Subject: [PATCH] add text content --- _static/AbatractFactory_run.jpg | Bin 0 -> 15185 bytes _static/Builder_run.jpg | Bin 0 -> 15204 bytes _static/Singleton_run.jpg | Bin 0 -> 14932 bytes behavioral_patterns/command.rst | 161 +++++++++++++++++++ behavioral_patterns/mediator.rst | 178 +++++++++++++++++++++ behavioral_patterns/observer.rst | 157 +++++++++++++++++++ behavioral_patterns/state.rst | 182 ++++++++++++++++++++++ behavioral_patterns/strategy.rst | 164 +++++++++++++++++++ code/AbstractFactory/ConcreteFactory1.cpp | 6 - code/AbstractFactory/ConcreteFactory2.cpp | 2 - code/AbstractFactory/main.cfp | 14 +- code/Builder/Director.cpp | 9 -- code/Builder/main.cfp | 8 +- code/Builder/mingw5/Director.o | Bin 115826 -> 115826 bytes code/Builder/mingw5/main.exe | Bin 648776 -> 648776 bytes code/Singleton/main.cfp | 4 +- creational_patterns/abstract_factory.rst | 87 +++++++---- creational_patterns/builder.rst | 22 ++- creational_patterns/creational.rst | 3 + creational_patterns/singleton.rst | 114 ++++---------- index.rst | 2 +- structural_patterns/adapter.rst | 170 ++++++++++++++++++++ structural_patterns/bridge.rst | 176 +++++++++++++++++++++ structural_patterns/decorator.rst | 176 +++++++++++++++++++++ structural_patterns/facade.rst | 166 ++++++++++++++++++++ structural_patterns/flyweight.rst | 176 +++++++++++++++++++++ structural_patterns/proxy.rst | 178 +++++++++++++++++++++ 27 files changed, 2010 insertions(+), 145 deletions(-) create mode 100644 _static/AbatractFactory_run.jpg create mode 100644 _static/Builder_run.jpg create mode 100644 _static/Singleton_run.jpg create mode 100644 behavioral_patterns/command.rst create mode 100644 behavioral_patterns/mediator.rst create mode 100644 behavioral_patterns/observer.rst create mode 100644 behavioral_patterns/state.rst create mode 100644 behavioral_patterns/strategy.rst create mode 100644 structural_patterns/adapter.rst create mode 100644 structural_patterns/bridge.rst create mode 100644 structural_patterns/decorator.rst create mode 100644 structural_patterns/facade.rst create mode 100644 structural_patterns/flyweight.rst create mode 100644 structural_patterns/proxy.rst diff --git a/_static/AbatractFactory_run.jpg b/_static/AbatractFactory_run.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9e965d45de39daf53fbfb08f6eaa5f532b4a024b GIT binary patch literal 15185 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 R7;Uhf|M2X;JHW>?{|i}8zS;l) literal 0 HcmV?d00001 diff --git a/_static/Builder_run.jpg b/_static/Builder_run.jpg new file mode 100644 index 0000000000000000000000000000000000000000..14ec8a062989bfd7f3278789da5cf47af1e5c9ba GIT binary patch literal 15204 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.h ProductB2.cpp ProductB2.h -main.cpp +main.cpp AbstractFactory.cpp AbstractFactory.h AbstractProductA.cpp AbstractProductA.h AbstractProductB.cpp AbstractProductB.h -ConcreteFactory1.cpp -ConcreteFactory1.h -ConcreteFactory2.cpp +ConcreteFactory1.cpp +ConcreteFactory1.h +ConcreteFactory2.cpp ConcreteFactory2.h -ProductA1.cpp -ProductA1.h +ProductA1.cpp +ProductA1.h ProductA2.cpp -ProductB1.cpp +ProductB1.cpp ProductB2.cpp 111 mingw5 diff --git a/code/Builder/Director.cpp b/code/Builder/Director.cpp index 05bf2a3..4b1fce3 100644 --- a/code/Builder/Director.cpp +++ b/code/Builder/Director.cpp @@ -7,21 +7,12 @@ #include "Director.h" - Director::Director(){ - } - - Director::~Director(){ - } - - - - Product* Director::constuct(){ m_pbuilder->buildPartA(); m_pbuilder->buildPartB(); diff --git a/code/Builder/main.cfp b/code/Builder/main.cfp index 11027bc..aef7b91 100644 --- a/code/Builder/main.cfp +++ b/code/Builder/main.cfp @@ -18,12 +18,12 @@ Director.h Product.cpp Product.h -main.cpp -Builder.cpp +main.cpp +Builder.cpp Builder.h -ConcreteBuilder.cpp +ConcreteBuilder.cpp ConcreteBuilder.h -Director.cpp +Director.cpp Director.h Product.cpp Product.h diff --git a/code/Builder/mingw5/Director.o b/code/Builder/mingw5/Director.o index 5fc5ea3cbcd9a5374e960a2b8ebd3fc5c57e2f0d..ac69d064dd319b26d947cca7c854bc8dcc939f64 100644 GIT binary patch delta 639 zcmb7>FHFNg7{y;9VNKhE0-=9ahM@~M9Eu=FgFs-Xhad!lL{5O1Axk*iSh7u`a7Y{$ zLxM&Sd?kYLzFS)+F#D3r{d)J_`@Xh$x0ZKnk515W@B?7bw=jeQoBTq)<}T+_8PCfS zo-ZCUxbO;2xi505dkZNwo&_|?Wv0mf%~>!PuI>e4N1;yJk+CT=%EYE*GnGL>98wt@ zE=`avfo-mqX|Hg=oQqj=bTeFTE1c7NH>;Pu%Na&y1|PS~c{4fw)VuilIS5-T*eE8? zu!`M^*Kk~MfYX8{`HbtsB**w>vOAEE8=K^)U{BwKq5JoH61^4m;so{_kPk&qW{y2F ztY4$hO7vH>(@wBA)oY*pNll7%9MUV5k;@V;|ANdWH}+Wc4V+Z^Mk%Map)cc2tA5pw KpZc-&{_qQ~c|n^1 delta 689 zcmb7Bu}T9$5Phd$4wF+3A-Rn~A=wLdHew|fvRGKyT5BO zt&L!9A@)~Vh;KH#;RKru4Et{Oy*INrMZZ$?D^H8{UKKw826=!XstAc+h;MjGUBa;L zL-4%&Fo;ldSo2(BMh^irIkf;tiM^-L{`Fa~7g2UwZ}eg`DLb&T*p4!h#d6p%h#?9I zgB2`KAX@?(%p==A#vXkxX7$O^M$8$`slA_7%iey5k)1)|jy`YJN0r{9+{7|}v-Fl# ztjSG}Y0$#9qZyVDr+6Kw4okB$=7(+8#y6W)2lBt$wprq^-;ZJ4he4;bL;Yum*;aC; zG{QNc7>XS+b>Yb3>@{fwI{QjCk2Q9jpNz80{3J&s#XhwXhS-N-zc=BxnBk-FyEvKh VyPi&MH@j4wpmUw8=UfHv<6pB>LC63A diff --git a/code/Builder/mingw5/main.exe b/code/Builder/mingw5/main.exe index 6a5ae160f3e78b18126013ad7c619a1267b22bb6..0cf2a69d104656c39c2d960d8e917e411a31cd7e 100644 GIT binary patch delta 736 zcmX?cM*YMY^$8u!$*mR>yM38{Z*IKRdW*637E|jj=B>9_zD%#@VqjBnU}#>!$gqHc zi-CiIfk6exZUNFDaS(6;io*bi%?#zZFmN;QK-nrlnh%KA0QIT>)rbJ~-k*ao6Qm5Q zIrU%(OoNVq4dP``f*ZsOb{xbYUJwNaE)2X3Y;ZOo13#1va*zfP-+`Lrg~J?>{a`@I zpf6B^if|Z2tT{X@K_Mi-FbiUi05I4EkbEXEJ-?GhJY0xD4(={t1~WKYl)(?q7Gp?* zvO%8B0AhQv*^&%Qim=d^1RI?R6kos~$-px`a2AU=HzES1r@x-X(r+luAOO^HZ8k`i zG+4(QC>s>Nu=D^@0|G7#($iPZX39_zD$qcW?)lrU}#>!$gqHc zn}LIYfk6exZUNFDaS(6;io*bi%?#zZFz_<)K-nrlnh%KA0QIT>)rcre-`BySq=rxJ z5wKc81|@~*eG^&qraN@92yoqj3VI<6et`-WAq(=X1X(4?FiT1~WKYj=>MkmS;$VvO$i|0AhQviAoGiiVh6-=YRr42^=7qKyeTo=2;gY8wOk$ zlpz5EvfPD1W%}z`Ed7Qm3<5wiuFVGNQvsXt2FeDR0SjP|8V~?!TRodaKT(Cj1}p$n z0;KJL_{bWNCsi5z;7V1YDnQy);a&!*mjUAEVD)MYS#b4gNb1$5ThC!pW>jvEpTh#g TtU$~L#Oy%Ku|0kc=SxojGu&El diff --git a/code/Singleton/main.cfp b/code/Singleton/main.cfp index 92ed091..af33829 100644 --- a/code/Singleton/main.cfp +++ b/code/Singleton/main.cfp @@ -12,8 +12,8 @@ Singleton.cpp Singleton.h -main.cpp -Singleton.cpp +main.cpp +Singleton.cpp Singleton.h 111 mingw5 diff --git a/creational_patterns/abstract_factory.rst b/creational_patterns/abstract_factory.rst index 6701b84..6bc1c3b 100644 --- a/creational_patterns/abstract_factory.rst +++ b/creational_patterns/abstract_factory.rst @@ -3,36 +3,20 @@ 抽象工厂模式(Abstract Factory) ======================================== +.. contents:: 目录 + 模式动机 -------------------- -- 在工厂方法模式中具体工厂负责生产具体的产品,每一 -个具体工厂对应一种具体产品,工厂方法也具有唯一性, -一般情况下,一个具体工厂中只有一个工厂方法或者一 -组重载的工厂方法。但是有时候我们需要一个工厂可以 -提供多个产品对象,而不是单一的产品对象。 +- 在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。 为了更清晰地理解工厂方法模式,需要先引入两个概念: - * 产品等级结构:产品等级结构即产品的继承结构,如一个抽象 - 类是电视机,其子类有海尔电视机、海信电视机、TCL电视机, - 则抽象电视机与具体品牌的电视机之间构成了一个产品等级结 - 构,抽象电视机是父类,而具体品牌的电视机是其子类。 - * 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的, - 位于不同产品等级结构中的一组产品,如海尔电器工厂生产的 - 海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结 - 构中,海尔电冰箱位于电冰箱产品等级结构中。 - -- 当系统所提供的工厂所需生产的具体产品并不是一个简单的对象, -而是多个位于不同产品等级结构中属于不同类型的具体产品时需要 -使用抽象工厂模式。 -- 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一 -种形态。 -- 抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对 -的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级 -结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品 -对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等 -级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模 -式更为简单、有效率 + * **产品等级结构** :产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。 + * **产品族** :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。 + +- 当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。 +- 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。 +- 抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。 模式定义 @@ -58,12 +42,27 @@ 代码分析 -------------------- -.. literalinclude:: /code/SimpleFactory/Factory.cpp +.. literalinclude:: /code/AbstractFactory/main.cpp + :language: cpp + :linenos: + :lines: 1-21 + :emphasize-lines: 11-21 + +.. literalinclude:: /code/AbstractFactory/ConcreteFactory1.cpp + :language: cpp + :linenos: + :lines: 1-10,21-28 + :emphasize-lines: 11-18 + +.. literalinclude:: /code/AbstractFactory/ProductA1.cpp :language: cpp :linenos: - :lines: 1-10,24- - :emphasize-lines: 12-19 + :lines: 1-10,21-23 + :emphasize-lines: 11-13 +运行结果: + +.. image:: /_static/AbatractFactory_run.jpg 模式分析 @@ -74,20 +73,52 @@ 优点 -------------------- +- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。 +- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。 +- 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。 + 缺点 -------------------- +- 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。 +- 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。 + 适用环境 -------------------- +在以下情况下可以使用抽象工厂模式: + +- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。 +- 系统中有多于一个的产品族,而每次只使用其中某一产品族。 +- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。 +- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。 + 模式应用 -------------------- +在很多软件系统中需要更换界面主题,要求界面中的按钮、文本框、背景色等一起发生改变时,可以使用抽象工厂模式进行设计。 + 模式扩展 -------------------- +“开闭原则”的倾斜性 +^^^^^^^^^^^^^^^^^^^^^ + +- “开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面: + (1) 增加产品族:对于增加新的产品族,工厂方法模式很好的支持了“开闭原则”,对于新增加的产品族,只需要对应增加一个新的具体工厂即可,对已有代码无须做任何修改。 + (2) 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。 +- 抽象工厂模式的这种性质称为“开闭原则”的倾斜性,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,但不能为新的产品等级结构的增加提供这样的方便。 + +工厂模式的退化 +^^^^^^^^^^^^^^^^^^^^ +- 当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。 总结 -------------------- +- 抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。 +- 抽象工厂模式包含四个角色:抽象工厂用于声明生成抽象产品的方法;具体工厂实现了抽象工厂声明的生成抽象产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中;抽象产品为每种产品声明接口,在抽象产品中定义了产品的抽象业务方法;具体产品定义具体工厂生产的具体产品对象,实现抽象产品接口中定义的业务方法。 +- 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。 +- 抽象工厂模式的主要优点是隔离了具体类的生成,使得客户并不需要知道什么被创建,而且每次可以通过具体工厂类创建一个产品族中的多个对象,增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便;主要缺点在于增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。 +- 抽象工厂模式适用情况包括:一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节;系统中有多于一个的产品族,而每次只使用其中某一产品族;属于同一个产品族的产品将在一起使用;系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。 diff --git a/creational_patterns/builder.rst b/creational_patterns/builder.rst index 808804b..dd64d46 100644 --- a/creational_patterns/builder.rst +++ b/creational_patterns/builder.rst @@ -3,6 +3,8 @@ 建造者模式 ==================== +.. contents:: 目录 + 模式动机 -------------------- 无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮、方向盘、发送机等各种部件。而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。 @@ -38,12 +40,25 @@ 代码分析 -------------------- -.. literalinclude:: /code/SimpleFactory/Factory.cpp +.. literalinclude:: /code/Builder/main.cpp :language: cpp :linenos: :lines: 1- - :emphasize-lines: 12-19 + :emphasize-lines: 11-15 + +.. literalinclude:: /code/Builder/ConcreteBuilder.cpp + :language: cpp + :linenos: + :emphasize-lines: 21-33 + +.. literalinclude:: /code/Builder/Director.cpp + :language: cpp + :linenos: + :emphasize-lines: 16-21 + +运行结果: +.. image:: /_static/Builder_run.jpg 模式分析 @@ -114,8 +129,7 @@ Builder角色扮演指挥者与建造者双重角色。 - 建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。 - 建造者模式包含如下四个角色:抽象建造者为创建一个产品对象的各个部件指定抽象接口;具体建造者实现了抽象建造者接口,实现各个部件的构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象;产品角色是被构建的复杂对象,包含多个组成部件;指挥者负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造 - 在建造者模式的结构中引入了一个指挥者类,该类的作用主要有两个:一方面它隔离了客户与生产过程;另一方面它负责控制产品的生成过程。指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象。 -- 建造者模式的主要优点在于客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象,每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,符合“开闭原则”,还可以更加精细地控制产品的创建过程;其主要缺点在于由于建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,因此其使用范围受到一定的限制,如果产品 -的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。 +- 建造者模式的主要优点在于客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象,每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,符合“开闭原则”,还可以更加精细地控制产品的创建过程;其主要缺点在于由于建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,因此其使用范围受到一定的限制,如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。 - 建造者模式适用情况包括:需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性;需要生成的产品对象的属性相互依赖,需要指定其生成顺序;对象的创建过程独立于创建该对象的类;隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同类型的产品。 diff --git a/creational_patterns/creational.rst b/creational_patterns/creational.rst index 0d5fe3e..0c52951 100644 --- a/creational_patterns/creational.rst +++ b/creational_patterns/creational.rst @@ -31,5 +31,8 @@ simple_factory factory_method + abstract_factory + builder + singleton diff --git a/creational_patterns/singleton.rst b/creational_patterns/singleton.rst index e347194..36d1626 100644 --- a/creational_patterns/singleton.rst +++ b/creational_patterns/singleton.rst @@ -3,32 +3,22 @@ 单例模式 ==================== +.. contents:: 目录 + 模式动机 -------------------- -对于系统中的某些类来说,只有一个实例很重要,例如,一个系统 -中可以存在多个打印任务,但是只能有一个正在工作的任务;一个 -系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时 -工具或ID(序号)生成器。 +对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。 -如何保证一个类只有一个实例并且这个实例易于被访问 -呢?定义一个全局变量可以确保对象随时都可以被访问, -但不能防止我们实例化多个对象。 +如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。 -一个更好的解决办法是让类自身负责保存它的唯一实例。 -这个类可以保证没有其他实例被创建,并且它可以提供 -一个访问该实例的方法。这就是单例模式的模式动机。 +一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。 模式定义 -------------------- -单例模式(Singleton Pattern):单例模式确保某一个 -类只有一个实例,而且自行实例化并向整个系统提供这 -个实例,这个类称为单例类,它提供全局访问的方法。 +单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。 -单例模式的要点有三个:一是某个类只能有一个实例; -二是它必须自行创建这个实例;三是它必须自行向整个 -系统提供这个实例。单例模式是一种对象创建型模式。 -单例模式又名单件模式或单态模式。 +单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。 模式结构 @@ -46,24 +36,23 @@ 代码分析 -------------------- -.. literalinclude:: /code/SimpleFactory/Factory.cpp +.. literalinclude:: /code/Singleton/main.cpp + :language: cpp + :linenos: + :emphasize-lines: 7-8 + +.. literalinclude:: /code/Singleton/Singleton.cpp :language: cpp :linenos: - :lines: 1-10,24- - :emphasize-lines: 12-19 + :emphasize-lines: 21-28 +运行结果: +.. image:: /_static/Singleton_run.jpg 模式分析 -------------------- -单例模式的目的是保证一个类仅有一个实例,并提供一 -个访问它的全局访问点。单例模式包含的角色只有一个, -就是单例类——Singleton。单例类拥有一个私有构造 -函数,确保用户无法通过new关键字直接实例化它。除 -此之外,该模式中包含一个静态私有成员变量与静态公 -有的工厂方法,该工厂方法负责检验实例的存在性并实 -例化自己,然后存储在静态成员变量中,以确保只有一 -个实例被创建。 +单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式包含的角色只有一个,就是单例类——Singleton。单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它。除此之外,该模式中包含一个静态私有成员变量与静态公有的工厂方法,该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。 在单例模式的实现过程中,需要注意如下三点: @@ -74,58 +63,35 @@ 实例 -------------------- -在操作系统中,打印池(Print Spooler)是一个用于管理打印任务 -的应用程序,通过打印池用户可以删除、中止或者改变打印任 -务的优先级,在一个系统中只允许运行一个打印池对象,如果 -重复创建打印池则抛出异常。现使用单例模式来模拟实现打印 -池的设计 +在操作系统中,打印池(Print Spooler)是一个用于管理打印任务的应用程序,通过打印池用户可以删除、中止或者改变打印任务的优先级,在一个系统中只允许运行一个打印池对象,如果重复创建打印池则抛出异常。现使用单例模式来模拟实现打印池的设计。 优点 -------------------- -- 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实 -例,所以它可以严格控制客户怎样以及何时访问它,并为设计 -及开发团队提供了共享的概念。 -- 由于在系统内存中只存在一个对象,因此可以节约系统资源, -对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高 -系统的性能。 -- 允许可变数目的实例。我们可以基于单例模式进行扩展,使用 -与单例控制相似的方法来获得指定个数的对象实例。 +- 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。 +- 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。 +- 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。 缺点 -------------------- - 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。 -- 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单 -例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色, -包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。 -- 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象 -设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池 -溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动 -垃圾回收的技术,因此,如果实例化的对象长时间不被利用,系统会 -认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化, -这将导致对象状态的丢失 +- 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。 +- 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。 适用环境 -------------------- 在以下情况下可以使用单例模式: -- 系统只需要一个实例对象,如系统要求提供一个唯一的序列号 -生成器,或者需要考虑资源消耗太大而只允许创建一个对象。 -- 客户调用类的单个实例只允许使用一个公共访问点,除了该公 -共访问点,不能通过其他途径访问该实例。 -- 在一个系统中要求一个类只有一个实例时才应当使用单例模式。 -反过来,如果一个类可以有几个实例共存,就需要对单例模式 -进行改进,使之成为多例模式 +- 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。 +- 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。 +- 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式 模式应用 -------------------- -一个具有自动编号主键的表可以有多个用户同时使 -用,但数据库中只能有一个地方分配下一个主键编号, -否则会出现主键重复,因此该主键编号生成器必须具备 -唯一性,可以通过单例模式来实现。 +一个具有自动编号主键的表可以有多个用户同时使用,但数据库中只能有一个地方分配下一个主键编号,否则会出现主键重复,因此该主键编号生成器必须具备唯一性,可以通过单例模式来实现。 模式扩展 @@ -133,27 +99,11 @@ 总结 -------------------- -- 单例模式确保某一个类只有一个实例,而且自行实例化并 -向整个系统提供这个实例,这个类称为单例类,它提供全 -局访问的方法。单例模式的要点有三个:一是某个类只能 -有一个实例;二是它必须自行创建这个实例;三是它必须 -自行向整个系统提供这个实例。单例模式是一种对象创建 -型模式。 -- 单例模式只包含一个单例角色:在单例类的内部实现只生 -成一个实例,同时它提供一个静态的工厂方法,让客户可 -以使用它的唯一实例;为了防止在外部对其实例化,将其 -构造函数设计为私有。 -- 单例模式的目的是保证一个类仅有一个实例,并提供一个 -访问它的全局访问点。单例类拥有一个私有构造函数,确 -保用户无法通过new关键字直接实例化它。除此之外,该 -模式中包含一个静态私有成员变量与静态公有的工厂方法。 -该工厂方法负责检验实例的存在性并实例化自己,然后存 -储在静态成员变量中,以确保只有一个实例被创建。 -- 单例模式的主要优点在于提供了对唯一实例的受控访问并 -可以节约系统资源;其主要缺点在于因为缺少抽象层而难 -以扩展,且单例类职责过重。 -- 单例模式适用情况包括:系统只需要一个实例对象;客户 -调用类的单个实例只允许使用一个公共访问点。 +- 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。 +- 单例模式只包含一个单例角色:在单例类的内部实现只生成一个实例,同时它提供一个静态的工厂方法,让客户可以使用它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有。 +- 单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它。除此之外,该模式中包含一个静态私有成员变量与静态公有的工厂方法。该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。 +- 单例模式的主要优点在于提供了对唯一实例的受控访问并可以节约系统资源;其主要缺点在于因为缺少抽象层而难以扩展,且单例类职责过重。 +- 单例模式适用情况包括:系统只需要一个实例对象;客户调用类的单个实例只允许使用一个公共访问点。 diff --git a/index.rst b/index.rst index c0d67a1..68bff74 100644 --- a/index.rst +++ b/index.rst @@ -25,7 +25,7 @@ -------------------- - +ref: 《java设计模式》的课件; Indices and tables ================== diff --git a/structural_patterns/adapter.rst b/structural_patterns/adapter.rst new file mode 100644 index 0000000..543fc2e --- /dev/null +++ b/structural_patterns/adapter.rst @@ -0,0 +1,170 @@ +.. _adapter: + +适配器模式 +==================== + +.. contents:: 目录 + +模式动机 +-------------------- +- 在软件开发中采用类似于电源适配器的设计和编码技巧被称为适配 +器模式。 +- 通常情况下,客户端可以通过目标类的接口访问它所提供的服务。 +有时,现有的类可以满足客户类的功能需要,但是它所提供的接口 +不一定是客户类所期望的,这可能是因为现有类中方法名与目标类 +中定义的方法名不一致等原因所导致的。 +- 在这种情况下,现有的接口需要转化为客户类期望的接口,这样保 +证了对现有类的重用。如果不进行这样的转化,客户类就不能利用 +现有类所提供的功能,适配器模式可以完成这样的转化。 +- 在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这 +个包装类指的就是适配器(Adapter),它所包装的对象就是适配者 +(Adaptee),即被适配的类。 +- 适配器提供客户类需要的接口,适配器的实现就是把客户类的请求 +转化为对适配者的相应接口的调用。也就是说:当客户类调用适配 +器的方法时,在适配器类的内部将调用适配者类的方法,而这个过 +程对客户类是透明的,客户类并不直接访问适配者类。因此,适配 +器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适 +配器模式的模式动机。 + +模式定义 +-------------------- +适配器模式(Adapter Pattern) :将一个接口转换成客 +户希望的另一个接口,适配器模式使接口不兼容的那些 +类可以一起工作,其别名为包装器(Wrapper)。适配器 +模式既可以作为类结构型模式,也可以作为对象结构型 +模式。 + + + +模式结构 +-------------------- +适配器模式包含如下角色: + +- Target:目标抽象类 +- Adapter:适配器类 +- Adaptee:适配者类 +- Client:客户类 + +适配器模式有对象适配器和类适配器两种实现: + +对象适配器: + +类适配器: +.. image:: /_static/SimpleFactory.jpg + + +时序图 +-------------------- +.. image:: /_static/seq_SimpleFactory.jpg + +代码分析 +-------------------- +.. literalinclude:: /code/SimpleFactory/Factory.cpp + :language: cpp + :linenos: + :lines: 1-10,24- + :emphasize-lines: 12-19 + + +模式分析 +-------------------- + +实例 +-------------------- + +优点 +-------------------- +- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有 +的适配者类,而无须修改原有代码。 +- 增加了类的透明性和复用性,将具体的实现封装在适配者类中, +对于客户端类来说是透明的,而且提高了适配者的复用性。 +- 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地 +更换适配器,也可以在不修改原有代码的基础上增加新的适配 +器类,完全符合“开闭原则”。 + +类适配器模式还具有如下优点: + 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。 + +对象适配器模式还具有如下优点: + 一个对象适配器可以把多个不同的适配者适配到同一个目标, +也就是说,同一个适配器可以把适配者类和它的子类都适配到 +目标接口。 + + + +缺点 +-------------------- +类适配器模式的缺点如下: + 对于Java、C#等不支持多重继承的语言,一次最多只能适配一 +个适配者类,而且目标抽象类只能为抽象类,不能为具体类, +其使用有一定的局限性,不能将一个适配者类和它的子类都适 +配到目标接口。 + +对象适配器模式的缺点如下: + 与类适配器模式相比,要想置换适配者类的方法就不容易。如 +果一定要置换掉适配者类的一个或多个方法,就只好先做一个 +适配者类的子类,将适配者类的方法置换掉,然后再把适配者 +类的子类当做真正的适配者进行适配,实现过程较为复杂。 + + +适用环境 +-------------------- +在以下情况下可以使用适配器模式: + +- 系统需要使用现有的类,而这些类的接口不符合系统 +的需要。 +- 想要建立一个可以重复使用的类,用于与一些彼此之 +间没有太大关联的一些类,包括一些可能在将来引进 +的类一起工作。 + + +模式应用 +-------------------- +Sun公司在1996年公开了Java语言的数据库连接 +工具JDBC,JDBC使得Java语言程序能够与数据库连 +接,并使用SQL语言来查询和操作数据。JDBC给出一 +个客户端通用的抽象接口,每一个具体数据库引擎(如 +SQL Server、Oracle、MySQL等)的JDBC驱动软件 +都是一个介于JDBC接口和数据库引擎接口之间的适配 +器软件。抽象的JDBC接口和各个数据库引擎API之间 +都需要相应的适配器软件,这就是为各个不同数据库引 +擎准备的驱动程序。 + + +模式扩展 +-------------------- +认适配器模式(Default Adapter Pattern)或缺省适 +配器模式 + 当不需要全部实现接口提供的方法时,可先设计一个抽象 +类实现接口,并为该接口中每个方法提供一个默认实现 +(空方法),那么该抽象类的子类可有选择地覆盖父类的 +某些方法来实现需求,它适用于一个接口不想使用其所有 +的方法的情况。因此也称为单接口适配器模式。 + + +总结 +-------------------- +- 结构型模式描述如何将类或者对象结合在一起形成更大的结构。 +- 适配器模式用于将一个接口转换成客户希望的另一个接口,适配器模 +式使接口不兼容的那些类可以一起工作,其别名为包装器。适配器模 +式既可以作为类结构型模式,也可以作为对象结构型模式。 +- 适配器模式包含四个角色:目标抽象类定义客户要用的特定领域的接 +口;适配器类可以调用另一个接口,作为一个转换器,对适配者和抽 +象目标类进行适配,它是适配器模式的核心;适配者类是被适配的角 +色,它定义了一个已经存在的接口,这个接口需要适配;在客户类中 +针对目标抽象类进行编程,调用在目标抽象类中定义的业务方法。 +- 在类适配器模式中,适配器类实现了目标抽象类接口并继承了适配者 +类,并在目标抽象类的实现方法中调用所继承的适配者类的方法;在 +对象适配器模式中,适配器类继承了目标抽象类并定义了一个适配者 +类的对象实例,在所继承的目标抽象类方法中调用适配者类的相应业 +务方法。 +- 适配器模式的主要优点是将目标类和适配者类解耦,增加 +了类的透明性和复用性,同时系统的灵活性和扩展性都非 +常好,更换适配器或者增加新的适配器都非常方便,符合 +“开闭原则”;类适配器模式的缺点是适配器类在很多编 +程语言中不能同时适配多个适配者类,对象适配器模式的 +缺点是很难置换适配者类的方法。 +- 适配器模式适用情况包括:系统需要使用现有的类,而这 +些类的接口不符合系统的需要;想要建立一个可以重复使 +用的类,用于与一些彼此之间没有太大关联的一些类一起 +工作。 diff --git a/structural_patterns/bridge.rst b/structural_patterns/bridge.rst new file mode 100644 index 0000000..11f96ab --- /dev/null +++ b/structural_patterns/bridge.rst @@ -0,0 +1,176 @@ +.. _bridge: + +桥接模式 +==================== + +.. contents:: 目录 + +模式动机 +-------------------- +设想如果要绘制矩形、圆形、椭圆、正方形,我们至少 +需要4个形状类,但是如果绘制的图形需要具有不同的 +颜色,如红色、绿色、蓝色等,此时至少有如下两种设 +计方案: + +- 第一种设计方案是为每一种形状都提供一套各种颜色的版本。 +- 第二种设计方案是根据实际需要对形状和颜色进行组合 + +对于有两个变化维度(即两个变化的原因)的 +系统,采用方案二来进行设计系统中类的个数 +更少,且系统扩展更为方便。设计方案二即是 +桥接模式的应用。桥接模式将继承关系转换为 +关联关系,从而降低了类与类之间的耦合,减 +少了代码编写量。 + + +模式定义 +-------------------- +桥接模式(Bridge Pattern):将抽象部分与它的实现部 +分分离,使它们都可以独立地变化。它是一种对象结构 +型模式,又称为柄体(Handle and Body)模式或接口 +(Interface)模式。 + + +模式结构 +-------------------- +桥接模式包含如下角色: + +- Abstraction:抽象类 +- RefinedAbstraction:扩充抽象类 +- Implementor:实现类接口 +- ConcreteImplementor:具体实现类 + + +.. image:: /_static/SimpleFactory.jpg + + +时序图 +-------------------- +.. image:: /_static/seq_SimpleFactory.jpg + +代码分析 +-------------------- +.. literalinclude:: /code/SimpleFactory/Factory.cpp + :language: cpp + :linenos: + :lines: 1-10,24- + :emphasize-lines: 12-19 + + + +模式分析 +-------------------- +理解桥接模式,重点需要理解如何将抽象化(Abstraction)与实现化 +(Implementation)脱耦,使得二者可以独立地变化。 + +- 抽象化:抽象化就是忽略一些信息,把不同的实体当作同样的实体 +对待。在面向对象中,将对象的共同性质抽取出来形成类的过程即 +为抽象化的过程。 +- 实现化:针对抽象化给出的具体实现,就是实现化,抽象化与实现 +化是一对互逆的概念,实现化产生的对象比抽象化更具体,是对抽 +象化事物的进一步具体化的产物。 +- 脱耦:脱耦就是将抽象化和实现化之间的耦合解脱开,或者说是将 +它们之间的强关联改换成弱关联,将两个角色之间的继承关系改为 +关联关系。桥接模式中的所谓脱耦,就是指在一个软件系统的抽象 +化和实现化之间使用关联关系(组合或者聚合关系)而不是继承关 +系,从而使两者可以相对独立地变化,这就是桥接模式的用意。 + + +实例 +-------------------- +如果需要开发一个跨平台视频播放器,可以在不同操 +作系统平台(如Windows、Linux、Unix等)上播放 +多种格式的视频文件,常见的视频格式包括MPEG、 +RMVB、AVI、WMV等。现使用桥接模式设计该播放 +器。 + + +优点 +-------------------- +桥接模式的优点 +? 分离抽象接口及其实现部分。 +? 桥接模式有时类似于多继承方案,但是多继承方案违背了类的 +单一职责原则(即一个类只有一个变化的原因),复用性比较 +差,而且多继承结构中类的个数非常庞大,桥接模式是比多继 +承方案更好的解决方法。 +? 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展 +一个维度,都不需要修改原有系统。 +? 实现细节对客户透明,可以对用户隐藏实现细节。 + + +缺点 +-------------------- +桥接模式的缺点 +? 桥接模式的引入会增加系统的理解与设计难度,由于 +聚合关联关系建立在抽象层,要求开发者针对抽象进 +行设计与编程。 +? 桥接模式要求正确识别出系统中两个独立变化的维度, +因此其使用范围具有一定的局限性。 + + +适用环境 +-------------------- +在以下情况下可以使用桥接模式: +? 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的 +灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可 +以使它们在抽象层建立一个关联关系。 +? 抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在 +程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对 +象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。 +? 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。 +? 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化 +角色需要独立变化,设计要求需要独立管理这两者。 +? 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增 +加的系统,桥接模式尤为适用。 + + +模式应用 +-------------------- +一个Java桌面软件总是带有所在操作系统的视感 +(LookAndFeel),如果一个Java软件是在Unix系统上开发的, +那么开发人员看到的是Motif用户界面的视感;在Windows上面 +使用这个系统的用户看到的是Windows用户界面的视感;而一 +个在Macintosh上面使用的用户看到的则是Macintosh用户界面 +的视感,Java语言是通过所谓的Peer架构做到这一点的。Java +为AWT中的每一个GUI构件都提供了一个Peer构件,在AWT中 +的Peer架构就使用了桥接模式 + + +模式扩展 +-------------------- +适配器模式与桥接模式的联用 +? 桥接模式和适配器模式用于设计的不同阶段,桥接模式用于系 +统的初步设计,对于存在两个独立变化维度的类可以将其分为 +抽象化和实现化两个角色,使它们可以分别进行变化;而在初 +步设计完成之后,当发现系统与已有类无法协同工作时,可以 +采用适配器模式。但有时候在设计初期也需要考虑适配器模式, +特别是那些涉及到大量第三方应用接口的情况 + + +总结 +-------------------- +- 桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。 +它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口 +(Interface)模式。 +- 桥接模式包含如下四个角色:抽象类中定义了一个实现类接口类型的 +对象并可以维护该对象;扩充抽象类扩充由抽象类定义的接口,它实 +现了在抽象类中定义的抽象业务方法,在扩充抽象类中可以调用在实 +现类接口中定义的业务方法;实现类接口定义了实现类的接口,实现 +类接口仅提供基本操作,而抽象类定义的接口可能会做更多更复杂的 +操作;具体实现类实现了实现类接口并且具体实现它,在不同的具体 +实现类中提供基本操作的不同实现,在程序运行时,具体实现类对象 +将替换其父类对象,提供给客户端具体的业务操作方法。 +- 在桥接模式中,抽象化(Abstraction)与实现化(Implementation)脱耦, +它们可以沿着各自的维度独立变化。 +- 桥接模式的主要优点是分离抽象接口及其实现部分,是比多继承方案 +更好的解决方法,桥接模式还提高了系统的可扩充性,在两个变化维 +度中任意扩展一个维度,都不需要修改原有系统,实现细节对客户透 +明,可以对用户隐藏实现细节;其主要缺点是增加系统的理解与设计 +难度,且识别出系统中两个独立变化的维度并不是一件容易的事情。 +- 桥接模式适用情况包括:需要在构件的抽象化角色和具体化角色之间 +增加更多的灵活性,避免在两个层次之间建立静态的继承联系;抽象 +化角色和实现化角色可以以继承的方式独立扩展而互不影响;一个类 +存在两个独立变化的维度,且这两个维度都需要进行扩展;设计要求 +需要独立管理抽象化角色和具体化角色;不希望使用继承或因为多层 +次继承导致系统类的个数急剧增加的系统。 + diff --git a/structural_patterns/decorator.rst b/structural_patterns/decorator.rst new file mode 100644 index 0000000..e48da66 --- /dev/null +++ b/structural_patterns/decorator.rst @@ -0,0 +1,176 @@ +.. _decorator: + +装饰模式 +==================== + +.. contents:: 目录 + +模式动机 +-------------------- +一般有两种方式可以实现给一个类或对象增加行为: +? 继承机制,使用继承机制是给现有类添加功能的一种有效途径, +通过继承一个现有类可以使得子类在拥有自身方法的同时还拥 +有父类的方法。但是这种方法是静态的,用户不能控制增加行 +为的方式和时机。 +? 关联机制,即将一个类的对象嵌入另一个对象中,由另一个对 +象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们 +称这个嵌入的对象为装饰器(Decorator) + +装饰模式以对客户透明的方式动态地给一个对象附加上 +更多的责任,换言之,客户端并不会觉得对象在装饰前 +和装饰后有什么不同。装饰模式可以在不需要创造更多 +子类的情况下,将对象的功能加以扩展。这就是装饰模 +式的模式动机。 + + +模式定义 +-------------------- +装饰模式(Decorator Pattern) :动态地给一个对象增 +加一些额外的职责(Responsibility),就增加对象功能 +来说,装饰模式比生成子类实现更为灵活。其别名也可 +以称为包装器(Wrapper),与适配器模式的别名相同, +但它们适用于不同的场合。根据翻译的不同,装饰模式 +也有人称之为“油漆工模式”,它是一种对象结构型模 +式。 + + +模式结构 +-------------------- +装饰模式包含如下角色: +? Component: 抽象构件 +? ConcreteComponent: 具体构件 +? Decorator: 抽象装饰类 +? ConcreteDecorator: 具体装饰类 + + +.. image:: /_static/SimpleFactory.jpg + + +时序图 +-------------------- +.. image:: /_static/seq_SimpleFactory.jpg + +代码分析 +-------------------- +.. literalinclude:: /code/SimpleFactory/Factory.cpp + :language: cpp + :linenos: + :lines: 1-10,24- + :emphasize-lines: 12-19 + + + +模式分析 +-------------------- +- 与继承关系相比,关联关系的主要优势在于不会破坏类的封装 +性,而且继承是一种耦合度较大的静态关系,无法在程序运行 +时动态扩展。在软件开发阶段,关联关系虽然不会比继承关系 +减少编码量,但是到了软件维护阶段,由于关联关系使系统具 +有较好的松耦合性,因此使得系统更加容易维护。当然,关联 +关系的缺点是比继承关系要创建更多的对象。 +- 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的 +方式动态地给一个对象附加更多的责任。装饰模式可以在不需 +要创造更多子类的情况下,将对象的功能加以扩展。 + + +实例 +-------------------- +实例:变形金刚 + +变形金刚在变形之前是一辆汽车,它 +可以在陆地上移动。当它变成机器人 +之后除了能够在陆地上移动之外,还 +可以说话;如果需要,它还可以变成 +飞机,除了在陆地上移动还可以在天 +空中飞翔。 + + +优点 +-------------------- +装饰模式的优点 +? 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可 +以提供比继承更多的灵活性。 +? 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以 +在运行时选择不同的装饰器,从而实现不同的行为。 +? 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出 +很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得 +到功能更为强大的对象。 +? 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的 +具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须 +改变,符合“开闭原则” + + +缺点 +-------------------- +装饰模式的缺点 +? 使用装饰模式进行系统设计时将产生很多小对象,这些对象的 +区别在于它们之间相互连接的方式有所不同,而不是它们的类 +或者属性值有所不同,同时还将产生很多具体装饰类。这些装 +饰类和小对象的产生将增加系统的复杂度,加大学习与理解的 +难度。 +? 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继 +承更加易于出错,排错也很困难,对于多次装饰的对象,调试 +时寻找错误可能需要逐级排查,较为烦琐。 + + +适用环境 +-------------------- +在以下情况下可以使用装饰模式: +? 在不影响其他对象的情况下,以动态、透明的方式给单个对象 +添加职责。 +? 需要动态地给一个对象增加功能,这些功能也可以动态地被撤 +销。 +? 当不能采用继承的方式对系统进行扩充或者采用继承不利于系 +统扩展和维护时。不能采用继承的情况主要有两类:第一类是 +系统中存在大量独立的扩展,为支持每一种组合将产生大量的 +子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能 +继承(如final类) + + +模式应用 +-------------------- + +模式扩展 +-------------------- +装饰模式的简化-需要注意的问题 +? 一个装饰类的接口必须与被装饰类的接口保持相同,对于客户 +端来说无论是装饰之前的对象还是装饰之后的对象都可以一致 +对待。 +? 尽量保持具体构件类Component作为一个“轻”类,也就是说 +不要把太多的逻辑和状态放在具体构件类中,可以通过装饰类 +对其进行扩展。 +? 如果只有一个具体构件类而没有抽象构件类,那么抽象装饰类 +可以作为具体构件类的直接子类。 + + +总结 +-------------------- +- 装饰模式用于动态地给一个对象增加一些额外的职责,就增加对象功 +能来说,装饰模式比生成子类实现更为灵活。它是一种对象结构型模 +式。 +- 装饰模式包含四个角色:抽象构件定义了对象的接口,可以给这些对 +象动态增加职责(方法);具体构件定义了具体的构件对象,实现了 +在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法); +抽象装饰类是抽象构件类的子类,用于给具体构件增加职责,但是具 +体职责在其子类中实现;具体装饰类是抽象装饰类的子类,负责向构 +件添加新的职责。 +- 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动 +态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子 +类的情况下,将对象的功能加以扩展。 +- 装饰模式的主要优点在于可以提供比继承更多的灵活性,可以通过一种动态的 +方式来扩展一个对象的功能,并通过使用不同的具体装饰类以及这些装饰类的 +排列组合,可以创造出很多不同行为的组合,而且具体构件类与具体装饰类可 +以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类;其主要缺 +点在于使用装饰模式进行系统设计时将产生很多小对象,而且装饰模式比继承 +更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需 +要逐级排查,较为烦琐。 +- 装饰模式适用情况包括:在不影响其他对象的情况下,以动态、透明的方式给 +单个对象添加职责;需要动态地给一个对象增加功能,这些功能也可以动态地 +被撤销;当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展 +和维护时。 +- 装饰模式可分为透明装饰模式和半透明装饰模式:在透明装饰模式中,要求客 +户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该声明具体构 +件类型和具体装饰类型,而应该全部声明为抽象构件类型;半透明装饰模式允 +许用户在客户端声明具体装饰者类型的对象,调用在具体装饰者中新增的方法。 + + diff --git a/structural_patterns/facade.rst b/structural_patterns/facade.rst new file mode 100644 index 0000000..700787d --- /dev/null +++ b/structural_patterns/facade.rst @@ -0,0 +1,166 @@ +.. _facade: + +外观模式 +==================== + +.. contents:: 目录 + +模式动机 +-------------------- + +模式定义 +-------------------- +外观模式(Facade Pattern):外部与一个子系统的通 +信必须通过一个统一的外观对象进行,为子系统中的一 +组接口提供一个一致的界面,外观模式定义了一个高层 +接口,这个接口使得这一子系统更加容易使用。外观模 +式又称为门面模式,它是一种对象结构型模式。 + + +模式结构 +-------------------- +外观模式包含如下角色: +? Facade: 外观角色 +? SubSystem:子系统角色 + + +.. image:: /_static/SimpleFactory.jpg + + +时序图 +-------------------- +.. image:: /_static/seq_SimpleFactory.jpg + +代码分析 +-------------------- +.. literalinclude:: /code/SimpleFactory/Factory.cpp + :language: cpp + :linenos: + :lines: 1-10,24- + :emphasize-lines: 12-19 + + + +模式分析 +-------------------- +根据“单一职责原则”,在软件中将一个系统划分为若干个子 +系统有利于降低整个系统的复杂性,一个常见的设计目标是使 +子系统间的通信和相互依赖关系达到最小,而达到该目标的途 +径之一就是引入一个外观对象,它为子系统的访问提供了一个 +简单而单一的入口。 +?外观模式也是“迪米特法则”的体现,通过引入一个新的外观 +类可以降低原有系统的复杂度,同时降低客户类与子系统类的 +耦合度。 +- 外观模式要求一个子系统的外部与其内部的通信通过一个统一的 +外观对象进行,外观类将客户端与子系统的内部复杂性分隔开, +使得客户端只需要与外观对象打交道,而不需要与子系统内部的 +很多对象打交道。 +?外观模式的目的在于降低系统的复杂程度。 +?外观模式从很大程度上提高了客户端使用的便捷性,使得客户端 +无须关心子系统的工作细节,通过外观角色即可调用相关功能。 + +实例 +-------------------- + +优点 +-------------------- +外观模式的优点 +? 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使 +用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之 +关联的对象也很少。 +? 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不 +会影响到调用它的客户类,只需要调整外观类即可。 +? 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间 +的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。 +一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化 +也不会影响到外观对象。 +? 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系 +统类。 + + +缺点 +-------------------- +外观模式的缺点 +? 不能很好地限制客户使用子系统类,如果对客户访问子系统类 +做太多的限制则减少了可变性和灵活性。 +? 在不引入抽象外观类的情况下,增加新的子系统可能需要修改 +外观类或客户端的源代码,违背了“开闭原则”。 + + +适用环境 +-------------------- +在以下情况下可以使用外观模式: +? 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。 +该接口可以满足大多数用户的需求,而且用户也可以越过外观 +类直接访问子系统。 +? 客户程序与多个子系统之间存在很大的依赖性。引入外观类将 +子系统与客户以及其他子系统解耦,可以提高子系统的独立性 +和可移植性。 +? 在层次化结构中,可以使用外观模式定义系统中每一层的入口, +层与层之间不直接产生联系,而通过外观类建立联系,降低层 +之间的耦合度。 + + +模式应用 +-------------------- + +模式扩展 +-------------------- +一个系统有多个外观类 +? 在外观模式中,通常只需要一个外观类,并且此外观类只有一 +个实例,换言之它是一个单例类。在很多情况下为了节约系统 +资源,一般将外观类设计为单例类。当然这并不意味着在整个 +系统里只能有一个外观类,在一个系统中可以设计多个外观类, +每个外观类都负责和一些特定的子系统交互,向用户提供相应 +的业务功能。 + +不要试图通过外观类为子系统增加新行为 +? 不要通过继承一个外观类在子系统中加入新的行为,这种做法 +是错误的。外观模式的用意是为子系统提供一个集中化和简化 +的沟通渠道,而不是向子系统加入新的行为,新的行为的增加 +应该通过修改原有子系统类或增加新的子系统类来实现,不能 +通过外观类来实现。 + +外观模式与迪米特法则 +? 外观模式创造出一个外观对象,将客户端所涉及的属于一个子 +系统的协作伙伴的数量减到最少,使得客户端与子系统内部的 +对象的相互作用被外观对象所取代。外观类充当了客户类与子 +系统类之间的“第三者”,降低了客户类与子系统类之间的耦 +合度,外观模式就是实现代码重构以便达到“迪米特法则”要 +求的一个强有力的武器。 + +抽象外观类的引入 +? 外观模式最大的缺点在于违背了“开闭原则”,当增加新的子 +系统或者移除子系统时需要修改外观类,可以通过引入抽象外 +观类在一定程度上解决该问题,客户端针对抽象外观类进行编 +程。对于新的业务需求,不修改原有外观类,而对应增加一个 +新的具体外观类,由新的具体外观类来关联新的子系统对象, +同时通过修改配置文件来达到不修改源代码并更换外观类的目 +的。 + + +总结 +-------------------- +在外观模式中,外部与一个子系统的通信必须通过一个统一的外观对 +象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义 +了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式 +又称为门面模式,它是一种对象结构型模式。 +? 外观模式包含两个角色:外观角色是在客户端直接调用的角色,在外 +观角色中可以知道相关的(一个或者多个)子系统的功能和责任,它将所 +有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统 +对象处理;在软件系统中可以同时有一个或者多个子系统角色,每一 +个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统 +的功能。 +? 外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观 +对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户 +端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交 +道。 +外观模式主要优点在于对客户屏蔽子系统组件,减少了客户处理的对 +象数目并使得子系统使用起来更加容易,它实现了子系统与客户之间 +的松耦合关系,并降低了大型软件系统中的编译依赖性,简化了系统 +在不同平台之间的移植过程;其缺点在于不能很好地限制客户使用子 +系统类,而且在不引入抽象外观类的情况下,增加新的子系统可能需 +要修改外观类或客户端的源代码,违背了“开闭原则”。 +? 外观模式适用情况包括:要为一个复杂子系统提供一个简单接口;客 +户程序与多个子系统之间存在很大的依赖性;在层次化结构中,需要 +定义系统中每一层的入口,使得层与层之间不直接产生联系。 diff --git a/structural_patterns/flyweight.rst b/structural_patterns/flyweight.rst new file mode 100644 index 0000000..1578890 --- /dev/null +++ b/structural_patterns/flyweight.rst @@ -0,0 +1,176 @@ +.. _flyweight: + +享元模式 +==================== + +.. contents:: 目录 + +模式动机 +-------------------- +面向对象技术可以很好地解决一些灵活性或可扩展性问 +题,但在很多情况下需要在系统中增加类和对象的个数。 +当对象数量太多时,将导致运行代价过高,带来性能下 +降等问题。 +?享元模式正是为解决这一类问题而诞生的。享元模式通 +过共享技术实现相同或相似对象的重用。 +- 在享元模式中可以共享的相同内容称为内部状态(Intrinsic +State),而那些需要外部环境来设置的不能共享的内容称为 +外部状态(Extrinsic State),由于区分了内部状态和外部状 +态,因此可以通过设置不同的外部状态使得相同的对象可以 +具有一些不同的特征,而相同的内部状态是可以共享的。 +- 在享元模式中通常会出现工厂模式,需要创建一个享元工厂 +来负责维护一个享元池(Flyweight Pool)用于存储具有相同 +内部状态的享元对象。 +- 在享元模式中共享的是享元对象的内部状态,外部状态 +需要通过环境来设置。在实际使用中,能够共享的内部 +状态是有限的,因此享元对象一般都设计为较小的对象, +它所包含的内部状态较少,这种对象也称为细粒度对象。 +享元模式的目的就是使用共享技术来实现大量细粒度对 +象的复用 + + +模式定义 +-------------------- +享元模式(Flyweight Pattern):运用共享技术有效地 +支持大量细粒度对象的复用。系统只使用少量的对象, +而这些对象都很相似,状态变化很小,可以实现对象的 +多次复用。由于享元模式要求能够共享的对象必须是细 +粒度对象,因此它又称为轻量级模式,它是一种对象结 +构型模式。 + + +模式结构 +-------------------- +享元模式包含如下角色: +? Flyweight: 抽象享元类 +? ConcreteFlyweight: 具体享元类 +? UnsharedConcreteFlyweight: 非共享具体享元类 +? FlyweightFactory: 享元工厂类 + + +.. image:: /_static/SimpleFactory.jpg + + +时序图 +-------------------- +.. image:: /_static/seq_SimpleFactory.jpg + +代码分析 +-------------------- +.. literalinclude:: /code/SimpleFactory/Factory.cpp + :language: cpp + :linenos: + :lines: 1-10,24- + :emphasize-lines: 12-19 + + + +模式分析 +-------------------- +享元模式是一个考虑系统性能的设计模式,通过使用 +享元模式可以节约内存空间,提高系统的性能。 + +享元模式的核心在于享元工厂类,享元工厂类的作用 +在于提供一个用于存储享元对象的享元池,用户需要 +对象时,首先从享元池中获取,如果享元池中不存在, +则创建一个新的享元对象返回给用户,并在享元池中 +保存该新增对象。 + +享元模式以共享的方式高效地支持大量的细粒度对象,享元对象 +能做到共享的关键是区分内部状态(Internal State)和外部状态 +(External State)。 +?(1) 内部状态是存储在享元对象内部并且不会随环境改变而改 +变的状态,因此内部状态可以共享。 +?(2) 外部状态是随环境改变而改变的、不可以共享的状态。享 +元对象的外部状态必须由客户端保存,并在享元对象被创建之 +后,在需要使用的时候再传入到享元对象内部。一个外部状态 +与另一个外部状态之间是相互独立的。 + + + +实例 +-------------------- + +优点 +-------------------- +享元模式的优点 +? 享元模式的优点在于它可以极大减少内存中对象的数 +量,使得相同对象或相似对象在内存中只保存一份。 +? 享元模式的外部状态相对独立,而且不会影响其内部 +状态,从而使得享元对象可以在不同的环境中被共享。 + + +缺点 +-------------------- +享元模式的缺点 +? 享元模式使得系统更加复杂,需要分离出内部状态和 +外部状态,这使得程序的逻辑复杂化。 +? 为了使对象可以共享,享元模式需要将享元对象的状 +态外部化,而读取外部状态使得运行时间变长。 + + +适用环境 +-------------------- +在以下情况下可以使用享元模式: +? 一个系统有大量相同或者相似的对象,由于这类对象 +的大量使用,造成内存的大量耗费。 +? 对象的大部分状态都可以外部化,可以将这些外部状 +态传入对象中。 +? 使用享元模式需要维护一个存储享元对象的享元池, +而这需要耗费资源,因此,应当在多次重复使用享元 +对象时才值得使用享元模式。 + + +模式应用 +-------------------- +享元模式在编辑器软件中大量使用,如在一个文 +档中多次出现相同的图片,则只需要创建一个图片对 +象,通过在应用程序中设置该图片出现的位置,可以 +实现该图片在不同地方多次重复显示。 + + + +模式扩展 +-------------------- +单纯享元模式和复合享元模式 + +- 单纯享元模式:在单纯享元模式中,所有的享元对象都是可以 +共享的,即所有抽象享元类的子类都可共享,不存在非共享具 +体享元类 +- 复合享元模式:将一些单纯享元使用组合模式加以组合,可以 +形成复合享元对象,这样的复合享元对象本身不能共享,但是 +它们可以分解成单纯享元对象,而后者则可以共享。 + +享元模式与其他模式的联用 +? 在享元模式的享元工厂类中通常提供一个静态的工厂方法 +用于返回享元对象,使用简单工厂模式来生成享元对象。 +? 在一个系统中,通常只有唯一一个享元工厂,因此享元工 +厂类可以使用单例模式进行设计。 +? 享元模式可以结合组合模式形成复合享元模式,统一对享 +元对象设置外部状态。 + + +总结 +-------------------- +享元模式运用共享技术有效地支持大量细粒度对象的复用。系统 +只使用少量的对象,而这些对象都很相似,状态变化很小,可以 +实现对象的多次复用,它是一种对象结构型模式。 +? 享元模式包含四个角色:抽象享元类声明一个接口,通过它可以 +接受并作用于外部状态;具体享元类实现了抽象享元接口,其实 +例称为享元对象;非共享具体享元是不能被共享的抽象享元类的 +子类;享元工厂类用于创建并管理享元对象,它针对抽象享元类 +编程,将各种类型的具体享元对象存储在一个享元池中。 +? 享元模式以共享的方式高效地支持大量的细粒度对象,享元对象 +能做到共享的关键是区分内部状态和外部状态。其中内部状态是 +存储在享元对象内部并且不会随环境改变而改变的状态,因此内 +部状态可以共享;外部状态是随环境改变而改变的、不可以共享 +的状态。 +?享元模式主要优点在于它可以极大减少内存中对象的数量, +使得相同对象或相似对象在内存中只保存一份;其缺点是 +使得系统更加复杂,并且需要将享元对象的状态外部化, +而读取外部状态使得运行时间变长。 +?享元模式适用情况包括:一个系统有大量相同或者相似的 +对象,由于这类对象的大量使用,造成内存的大量耗费; +对象的大部分状态都可以外部化,可以将这些外部状态传 +入对象中;多次重复使用享元对象。 + diff --git a/structural_patterns/proxy.rst b/structural_patterns/proxy.rst new file mode 100644 index 0000000..4028a62 --- /dev/null +++ b/structural_patterns/proxy.rst @@ -0,0 +1,178 @@ +.. _proxy: + +代理模式 +==================== + +.. contents:: 目录 + +模式动机 +-------------------- +在某些情况下,一个客户不想或者不能直接引用一个对 +象,此时可以通过一个称之为“代理”的第三者来实现 +间接引用。代理对象可以在客户端和目标对象之间起到 +中介的作用,并且可以通过代理对象去掉客户不能看到 +的内容和服务或者添加客户需要的额外服务。 + +通过引入一个新的对象(如小图片和远程代理 +对象)来实现对真实对象的操作或者将新的对 +象作为真实对象的一个替身,这种实现机制即 +为代理模式,通过引入代理对象来间接访问一 +个对象,这就是代理模式的模式动机。 + + +模式定义 +-------------------- +代理模式(Proxy Pattern) :给某一个对象提供一个代 +理,并由代理对象控制对原对象的引用。代理模式的英 +文叫做Proxy或Surrogate,它是一种对象结构型模式。 + + +模式结构 +-------------------- +代理模式包含如下角色: +? Subject: 抽象主题角色 +? Proxy: 代理主题角色 +? RealSubject: 真实主题角色 + + +.. image:: /_static/SimpleFactory.jpg + + +时序图 +-------------------- +.. image:: /_static/seq_SimpleFactory.jpg + +代码分析 +-------------------- +.. literalinclude:: /code/SimpleFactory/Factory.cpp + :language: cpp + :linenos: + :lines: 1-10,24- + :emphasize-lines: 12-19 + + + +模式分析 +-------------------- + +实例 +-------------------- + +优点 +-------------------- +代理模式的优点 +? 代理模式能够协调调用者和被调用者,在一定程度上降低了系 +统的耦合度。 +? 远程代理使得客户端可以访问在远程机器上的对象,远程机器 +可能具有更好的计算性能与处理速度,可以快速响应并处理客 +户端请求。 +? 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系 +统资源的消耗,对系统进行优化并提高运行速度。 +? 保护代理可以控制对真实对象的使用权限 + + + +缺点 +-------------------- +代理模式的缺点 +? 由于在客户端和真实主题之间增加了代理对象,因此 +有些类型的代理模式可能会造成请求的处理速度变慢。 +? 实现代理模式需要额外的工作,有些代理模式的实现 +非常复杂。 + + +适用环境 +-------------------- +根据代理模式的使用目的,常见的代理模式有以下几种类型: +? 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个本地 +的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在 +另一台主机中,远程代理又叫做大使(Ambassador)。 +? 虚拟(Virtual)代理:如果需要创建一个资源消耗较大的对象,先创建一 +个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。 +? Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟 +到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个 +开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象 +被用到的时候才被克隆。 +- 保护(Protect or Access)代理:控制对一个对象的访问,可以给 +不同的用户提供不同级别的使用权限。 +? 缓冲(Cache)代理:为某一个目标操作的结果提供临时的存储空 +间,以便多个客户端可以共享这些结果。 +? 防火墙(Firewall)代理:保护目标不让恶意用户接近。 +? 同步化(Synchronization)代理:使几个用户能够同时使用一个对 +象而没有冲突。 +? 智能引用(Smart Reference)代理:当一个对象被引用时,提供 +一些额外的操作,如将此对象被调用的次数记录下来等。 + + +模式应用 +-------------------- +EJB、Web Service等分布式技术都是代理模式 +的应用。在EJB中使用了RMI机制,远程服务器中的 +企业级Bean在本地有一个桩代理,客户端通过桩来调 +用远程对象中定义的方法,而无须直接与远程对象交 +互。在EJB的使用中需要提供一个公共的接口,客户 +端针对该接口进行编程,无须知道桩以及远程EJB的 +实现细节 + + +模式扩展 +-------------------- +几种常用的代理模式 +? 图片代理:一个很常见的代理模式的应用实例就是对大图浏览的控制。 +? 用户通过浏览器访问网页时先不加载真实的大图,而是通过代理对象 +的方法来进行处理,在代理对象的方法中,先使用一个线程向客户端 +浏览器加载一个小图片,然后在后台使用另一个线程来调用大图片的 +加载方法将大图片加载到客户端。当需要浏览大图片时,再将大图片 +在新网页中显示。如果用户在浏览大图时加载工作还没有完成,可以 +再启动一个线程来显示相应的提示信息。通过代理技术结合多线程编 +程将真实图片的加载放到后台来操作,不影响前台图片的浏览。 +- 远程代理:远程代理可以将网络的细节隐藏起来,使得客户端 +不必考虑网络的存在。客户完全可以认为被代理的远程业务对 +象是局域的而不是远程的,而远程代理对象承担了大部分的网 +络通信工作。 +- 虚拟代理:当一个对象的加载十分耗费资源的时候,虚拟代理 +的优势就非常明显地体现出来了。虚拟代理模式是一种内存节 +省技术,那些占用大量内存或处理复杂的对象将推迟到使用它 +的时候才创建。 +?在应用程序启动的时候,可以用代理对象代替真实对象初始化, +节省了内存的占用,并大大加速了系统的启动时间。 + +动态代理 +? 动态代理是一种较为高级的代理模式,它的典型应用就是Spring AOP。 +? 在传统的代理模式中,客户端通过Proxy调用RealSubject类的request() +方法,同时还在代理类中封装了其他方法(如preRequest()和 +postRequest()),可以处理一些其他问题。 +? 如果按照这种方法使用代理模式,那么真实主题角色必须是事先已经 +存在的,并将其作为代理对象的内部成员属性。如果一个真实主题角 +色必须对应一个代理主题角色,这将导致系统中的类个数急剧增加, +因此需要想办法减少系统中类的个数,此外,如何在事先不知道真实 +主题角色的情况下使用代理主题角色,这都是动态代理需要解决的问 +题。 + + + +总结 +-------------------- +在代理模式中,要求给某一个对象提供一个代理,并由代理对象控制 +对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对 +象结构型模式。 +? 代理模式包含三个角色:抽象主题角色声明了真实主题和代理主题的 +共同接口;代理主题角色内部包含对真实主题的引用,从而可以在任 +何时候操作真实主题对象;真实主题角色定义了代理角色所代表的真 +实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过 +代理主题角色间接调用真实主题角色中定义的方法。 +? 代理模式的优点在于能够协调调用者和被调用者,在一定程度上降低 +了系统的耦合度;其缺点在于由于在客户端和真实主题之间增加了代 +理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢, +并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂。 +远程代理为一个位于不同的地址空间的对象提供一个本地的代表对象, +它使得客户端可以访问在远程机器上的对象,远程机器可能具有更好 +的计算性能与处理速度,可以快速响应并处理客户端请求。 +? 如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的 +对象来表示,真实对象只在需要时才会被真正创建,这个小对象称为 +虚拟代理。虚拟代理通过使用一个小对象来代表一个大对象,可以减 +少系统资源的消耗,对系统进行优化并提高运行速度。 +? 保护代理可以控制对一个对象的访问,可以给不同的用户提供不同级 +别的使用权限。 + +