@@ -381,7 +381,7 @@ class BridgePattern {
381
381
}
382
382
}
383
383
```
384
- #### [ 组合模式]
384
+ #### 组合模式
385
385
把多个对象组成树状结构来表示局部与整体,这样用户可以一样的对待单个对象和对象的组合。
386
386
387
387
如文件如文件夹都看作一个条目,就形成目录结构。
@@ -501,7 +501,7 @@ public class Main {
501
501
}
502
502
```
503
503
参考书籍:图解设计模式(ISBN国际标准书号: 9787115439499)
504
- #### [ 修饰模式]
504
+ #### [ 修饰模式] (装饰模式)
505
505
向某个对象动态地添加更多的功能。修饰模式是除类继承外另一种扩展功能的方法。
506
506
``` java
507
507
// The Window interface class
@@ -599,7 +599,7 @@ description:simple window
599
599
description:simple window, including horizontal scrollbars
600
600
description:simple window, including horizontal scrollbars, including vertical scrollbars
601
601
```
602
- #### [ 外观模式]
602
+ #### [ 外观模式] (门面模式)
603
603
为子系统中的一组接口提供一个一致的界面, 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
604
604
``` java
605
605
// 这是一个抽象的示例。一个客户“you”通过外观接口“computer”启动计算机。
@@ -649,9 +649,307 @@ class You {
649
649
```
650
650
#### [ 享元模式]
651
651
通过共享以便有效的支持大量小颗粒对象。
652
+ ``` java
653
+ // 享元模式利用只加载执行任务时所必需的最少资料,因而减少内存使用量。
654
+ public enum FontEffect {
655
+ BOLD , ITALIC , SUPERSCRIPT , SUBSCRIPT , STRIKETHROUGH
656
+ }
657
+
658
+ public final class FontData {
659
+ // A weak hash map will drop unused references to FontData.
660
+ // Values have to be wrapped in WeakReferences,
661
+ // because value objects in weak hash map are held by strong references.
662
+ private static final WeakHashMap<FontData , WeakReference<FontData > > FLY_WEIGHT_DATA =
663
+ new WeakHashMap<FontData , WeakReference<FontData > > ();
664
+ private final int pointSize;
665
+ private final String fontFace;
666
+ private final Color color;
667
+ private final Set<FontEffect > effects;
668
+
669
+ private FontData (int pointSize , String fontFace , Color color , EnumSet<FontEffect > effects ) {
670
+ this . pointSize = pointSize;
671
+ this . fontFace = fontFace;
672
+ this . color = color;
673
+ this . effects = Collections . unmodifiableSet(effects);
674
+ }
675
+
676
+ public static FontData create (int pointSize , String fontFace , Color color ,
677
+ FontEffect ... effects ) {
678
+ EnumSet<FontEffect > effectsSet = EnumSet . noneOf(FontEffect . class);
679
+ for (FontEffect fontEffect : effects) {
680
+ effectsSet. add(fontEffect);
681
+ }
682
+ // We are unconcerned with object creation cost, we are reducing overall memory consumption
683
+ // 我们不关心对象创建成本,我们在减少整体内存消耗
684
+ FontData data = new FontData (pointSize, fontFace, color, effectsSet);
685
+
686
+ // Retrieve previously created instance with the given values if it (still) exists
687
+ // 如果给定的值仍然存在的话,恢复先前创建的实例
688
+ WeakReference<FontData > ref = FLY_WEIGHT_DATA . get(data);
689
+ FontData result = (ref != null ) ? ref. get() : null ;
690
+
691
+ // Store new font data instance if no matching instance exists
692
+ // 如果没有匹配的实例存在的话,存储新的字体数据实例
693
+ if (result == null ) {
694
+ FLY_WEIGHT_DATA . put(data, new WeakReference<FontData > (data));
695
+ result = data;
696
+ }
697
+ // return the single immutable copy with the given values
698
+ return result;
699
+ }
700
+
701
+ @Override
702
+ public boolean equals (Object obj ) {
703
+ if (obj instanceof FontData ) {
704
+ if (obj == this ) {
705
+ return true ;
706
+ }
707
+ FontData other = (FontData ) obj;
708
+ return other. pointSize == pointSize && other. fontFace. equals(fontFace)
709
+ && other. color. equals(color) && other. effects. equals(effects);
710
+ }
711
+ return false ;
712
+ }
713
+
714
+ @Override
715
+ public int hashCode () {
716
+ return (pointSize * 37 + effects. hashCode() * 13 ) * fontFace. hashCode();
717
+ }
718
+
719
+ // Getters for the font data, but no setters. FontData is immutable.
720
+ }
721
+ ```
652
722
#### [ 代理模式]
653
723
为其他对象提供一个代理以控制对这个对象的访问。
724
+ ``` java
725
+ // ProxyImage 类别用来访问远程方法。
726
+ interface Image {
727
+ void displayImage ();
728
+ }
729
+
730
+ // on System A
731
+ class RealImage implements Image {
732
+ private String filename;
733
+ public RealImage (String filename ) {
734
+ this . filename = filename;
735
+ loadImageFromDisk();
736
+ }
737
+ private void loadImageFromDisk () {
738
+ System . out. println(" Loading " + filename);
739
+ }
740
+ public void displayImage () {
741
+ System . out. println(" Displaying " + filename);
742
+ }
743
+ }
744
+
745
+ // on System B
746
+ class ProxyImage implements Image {
747
+ private String filename;
748
+ private Image image;
749
+ public ProxyImage (String filename ) {
750
+ this . filename = filename;
751
+ }
752
+ public void displayImage () {
753
+ if (image == null )
754
+ image = new RealImage (filename);
755
+ image. displayImage();
756
+ }
757
+ }
758
+
759
+ class ProxyExample {
760
+ public static void main (String [] args ) {
761
+ Image image1 = new ProxyImage (" HiRes_10MB_Photo1" );
762
+ Image image2 = new ProxyImage (" HiRes_10MB_Photo2" );
763
+
764
+ image1. displayImage(); // loading necessary
765
+ image2. displayImage(); // loading necessary
766
+ }
767
+ }
768
+ ```
769
+ ``` text
770
+ 程序的输出为:
771
+ Loading HiRes_10MB_Photo1
772
+ Displaying HiRes_10MB_Photo1
773
+ Loading HiRes_10MB_Photo2
774
+ Displaying HiRes_10MB_Photo2
775
+ ```
776
+
654
777
## [ 行为型模式]
778
+ #### [ 责任链模式]
779
+ 为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。
780
+ 将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
781
+ ``` java
782
+ // 以下的日志类(logging)例子演示了该模式。
783
+ // 注意:该例子不是日志类的推荐实现方式。
784
+ // 每一个logging handler首先决定是否需要在该层做处理,然后将控制传递到下一个logging handler。
785
+ // 通常在责任链模式的实现中,如果在某一层已经处理了这个logger,那么这个logger就不会传递下去。
786
+ // 在我们这个例子中,消息会一直传递到最底层不管它是否已经被处理。
787
+
788
+ import java.util.* ;
789
+
790
+ abstract class Logger
791
+ {
792
+ public static int ERR = 3 ;
793
+ public static int NOTICE = 5 ;
794
+ public static int DEBUG = 7 ;
795
+ protected int mask;
796
+ // The next element in the chain of responsibility
797
+ protected Logger next;
798
+ public Logger setNext ( Logger l ){
799
+ next = l;
800
+ return this ;
801
+ }
802
+ public final void message ( String msg , int priority ){
803
+ if ( priority <= mask ) {
804
+ writeMessage( msg );
805
+ if ( next != null ) {
806
+ next. message( msg, priority );
807
+ }
808
+ }
809
+ }
810
+ protected abstract void writeMessage ( String msg );
811
+ }
812
+
813
+ class StdoutLogger extends Logger {
814
+ public StdoutLogger ( int mask ) { this . mask = mask; }
815
+ protected void writeMessage ( String msg ){
816
+ System . out. println( " Writting to stdout: " + msg );
817
+ }
818
+ }
819
+
820
+ class EmailLogger extends Logger {
821
+ public EmailLogger ( int mask ) { this . mask = mask; }
822
+ protected void writeMessage ( String msg ){
823
+ System . out. println( " Sending via email: " + msg );
824
+ }
825
+ }
826
+
827
+ class StderrLogger extends Logger {
828
+ public StderrLogger ( int mask ) { this . mask = mask; }
829
+ protected void writeMessage ( String msg ){
830
+ System . out. println( " Sending to stderr: " + msg );
831
+ }
832
+ }
833
+
834
+ public class ChainOfResponsibilityExample {
835
+ public static void main ( String [] args )
836
+ {
837
+ // Build the chain of responsibility
838
+ Logger l = new StdoutLogger ( Logger . DEBUG ). setNext(
839
+ new EmailLogger ( Logger . NOTICE ). setNext(
840
+ new StderrLogger ( Logger . ERR ) ) );
841
+ // Handled by StdoutLogger
842
+ l. message( " Entering function y." , Logger . DEBUG );
843
+ // Handled by StdoutLogger and EmailLogger
844
+ l. message( " Step1 completed." , Logger . NOTICE );
845
+ // Handled by all three loggers
846
+ l. message( " An error has occurred." , Logger . ERR );
847
+ }
848
+ }
849
+ ```
850
+ ``` text
851
+ 程序的输出是:
852
+ Writing to debug output: Entering function y.
853
+ Writing to debug output: Step1 completed.
854
+ Sending via e-mail: Step1 completed.
855
+ Writing to debug output: An error has occurred.
856
+ Sending via e-mail: An error has occurred.
857
+ Writing to stderr: An error has occurred.
858
+ ```
859
+ #### [ 命令模式]
860
+ 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可取消的操作。
861
+
862
+ 图片来源:[ wiki] ( https://upload.wikimedia.org/wikipedia/commons/8/8e/Command_Design_Pattern_Class_Diagram.png )
863
+
864
+ ![ 例子] ( /img/post/命令模式例子类图.png )
865
+ ``` java
866
+ import java.util.List ;
867
+ import java.util.ArrayList ;
868
+
869
+ /* The Command interface */
870
+ public interface Command {
871
+ void execute ();
872
+ }
873
+
874
+ /* The Invoker class */
875
+ public class Switch {
876
+ private List<Command > history = new ArrayList<Command > ();
877
+ public Switch () { }
878
+ public void storeAndExecute (Command cmd ) {
879
+ this . history. add(cmd); // optional
880
+ cmd. execute();
881
+ }
882
+ }
883
+
884
+ /* The Receiver class */
885
+ public class Light {
886
+ public Light () { }
887
+ public void turnOn () { System . out. println(" The light is on" ); }
888
+ public void turnOff () { System . out. println(" The light is off" ); }
889
+ }
890
+
891
+ /* The Command for turning on the light - ConcreteCommand #1 */
892
+ public class FlipUpCommand implements Command {
893
+ private Light theLight;
894
+ public FlipUpCommand (Light light ) { this . theLight = light; }
895
+ public void execute (){ theLight. turnOn(); }
896
+ }
897
+
898
+ /* The Command for turning off the light - ConcreteCommand #2 */
899
+ public class FlipDownCommand implements Command {
900
+ private Light theLight;
901
+ public FlipDownCommand (Light light ) { this . theLight = light; }
902
+ public void execute () { theLight. turnOff(); }
903
+ }
904
+
905
+ /* The test class or client */
906
+ public class PressSwitch {
907
+ public static void main (String [] args ){
908
+ Light lamp = new Light ();
909
+ Command switchUp = new FlipUpCommand (lamp);
910
+ Command switchDown = new FlipDownCommand (lamp);
911
+
912
+ Switch mySwitch = new Switch ();
913
+ try {
914
+ if (" ON" . equalsIgnoreCase(args[0 ])) {
915
+ mySwitch. storeAndExecute(switchUp);
916
+ } else if (" OFF" . equalsIgnoreCase(args[0 ])) {
917
+ mySwitch. storeAndExecute(switchDown);
918
+ } else {
919
+ System . out. println(" Argument \" ON\" or \" OFF\" is required." );
920
+ }
921
+ } catch (Exception e) {
922
+ System . out. println(" Arguments required." );
923
+ }
924
+ }
925
+ }
926
+ ```
927
+ #### 解释器模式
928
+ 给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
929
+ #### [ 迭代器模式]
930
+ 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
931
+ #### [ 中介者模式]
932
+ 包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。
933
+ 当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。
934
+ #### 备忘录模式
935
+ 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,
936
+ 将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
937
+ #### [ 观察者模式]
938
+ 在对象间定义一个一对多的联系性,由此当一个对象改变了状态,所有其他相关的对象会被通知并且自动刷新。
939
+ #### 状态模式
940
+ 让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能获取的状态创立一个状态类的子类。
941
+ 当系统的状态变化时,系统便改变所选的子类。
942
+ #### [ 策略模式]
943
+ 定义一个算法的系列,将其各个分装,并且使他们有交互性。策略模式使得算法在用户使用的时候能独立的改变。
944
+ #### [ 模板方法模式]
945
+ 模板方法模式准备一个抽象类,将部分逻辑以具体方法及具体构造子类的形式实现,
946
+ 然后声明一些抽象方法来迫使子类实现剩余的逻辑。
947
+ 不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。
948
+ 先构建一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
949
+ #### [ 访问者模式]
950
+ 封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改,接受这个操作的数据结构可以保持不变。
951
+ 访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,
952
+ 使得操作集合可以相对自由的演化。
655
953
656
954
---
657
955
## 常见问题
@@ -677,10 +975,18 @@ class You {
677
975
678
976
[ 适配器模式 ] : https://zh.wikipedia.org/wiki/适配器模式
679
977
[ 桥接模式 ] : https://zh.wikipedia.org/wiki/桥接模式
680
- [ 组合模式 ] : https://zh.wikipedia.org/wiki/组合模式
681
978
[ 修饰模式 ] : https://zh.wikipedia.org/wiki/修饰模式
682
979
[ 外观模式] : https://zh.wikipedia.org/wiki/外观模式
683
980
[ 享元模式 ] : https://zh.wikipedia.org/wiki/享元模式
684
981
[ 代理模式 ] : https://zh.wikipedia.org/wiki/代理模式
685
982
983
+ [ 责任链模式 ] : https://zh.wikipedia.org/wiki/责任链模式
984
+ [ 命令模式 ] : https://zh.wikipedia.org/wiki/命令模式
985
+ [ 迭代器模式 ] : https://zh.wikipedia.org/wiki/迭代器模式
986
+ [ 中介者模式 ] : https://zh.wikipedia.org/wiki/中介者模式
987
+ [ 观察者模式 ] : https://zh.wikipedia.org/wiki/观察者模式
988
+ [ 策略模式 ] : https://zh.wikipedia.org/wiki/策略模式
989
+ [ 模板方法模式 ] : https://zh.wikipedia.org/wiki/模板方法
990
+ [ 访问者模式 ] : https://zh.wikipedia.org/wiki/访问者模式
991
+
686
992
[ IBM-开发社区-适配器模式 ] : https://www.ibm.com/developerworks/cn/java/j-lo-adapter-pattern/index.html
0 commit comments