1、 Java设计模式 1.1 创建型模式 AbstractFactory ( 抽象工厂 ) FactoryMethod ( 工厂方法 ) Singleton ( 单态模式 ) Builder ( 建造者模式 ) Prototype ( 原型模式 ) 1.2 结构型模式 Adapter ( 适配器模式 ) Bridge ( 桥接模式 ) Composite ( 组合模式 ) Decorator ( 装配模式 ) Facade ( 外观模式 ) Flyweight ( 享元模式 ) Proxy ( 代理模式 ) 1.3 行为型模式 Cha
2、in of Responsibility ( 责任链模式 ) Command ( 命令模式 ) Interpreter ( 解释器模式 ) Iterator ( 迭代器模式 ) Mediator ( 中介者模式 ) Memento ( 备忘录模式 ) Observer ( 观察者模式 ) State ( 状态模式 ) Strategy ( 策略模式 ) TemplateMethod ( 模板方法 ) Visitor ( 访问者模式 ) Toney Chen的总结 Singleton设计模式 Singleton单类模式是最简单的设计模式,它的
3、主要作用是保证在程序运行生命周期中,使用了单类模式的类只能有一个实例对象存在。单类模式实现了类似C语言中全局变量的功能,单类模式常用于注册/查找的服务。 单类模式有两种实现方式:饱汉模式和饿汉模式,如下: 饱汉单类模式例子代码: [java] view plaincopy 1. public class Singleton1{ 2. //饱汉模式,声明时就创建实例对象 3. public static final Singleton1 instance = new Singleton1(); 4. //单类模式的构造方法必须为priva
4、te,以避免通过构造方法创建对象实例, 5. //并且必须显示声明构造方法,以防止使用默认构造方法 6. private Singleton1(){} 7. //单类模式必须对外提供获取实例对象的方法 8. public static Singleton1 geInstance(){ 9. return instance; 10. } 11. } 饿汉单类模式即延迟初始化单类方式,例子代码: [java] view plaincopy 1. publ
5、ic class Singleton2{ 2. //饿汉模式,声明时不创建实例对象 3. public static Singleton2 instance; 4. //单类模式的构造方法必须为private,以避免通过构造方法创建对象实例, 5. //并且必须显示声明构造方法,以防止使用默认构造方法 6. private Singleton2(){} 7. //单类模式必须对外提供获取实例对象的方法,延迟初始化的单类模式必须使用synchronized同步关键字,否则多线程情况下很容易
6、产生多个实例对象 8. public static synchronized Singleton2 geInstance(){ 9. //延迟初始化,只有当第一次使用时才创建对象实例 10. if(instance == null){ 11. return new Singleton2(); 12. } 13. return instance; 14. } 15. } 一般认
7、为饱汉模式要比饿汉模式更加安全。 上面两种Singleton单类设计模式的实现方式都隐藏有如下的问题: (1).虽然构造方式的访问修饰符为private,即除了自身以外其他任何类都无法调用,但是通过反射机制的setAccessiable(true)方法可以访问私有方法和属性。因此Singleton单类模式必须考虑这种例外情况。 (2).对象序列化之后再反序列化时会生成新的对象,因此当Singleton单类模式类实现序列化接口时,必须显式声明所有的字段为tranisent。 在JDK1.5之后引入了Enum枚举,因此在JDK1.5之后Singleton单类模式又有了第三种实现方式,也是最
8、好的实现方式,例子如下: [java] view plaincopy 1. public enum Singleton3{ 2. INSTANCE{ 3. public void doSomething(){ 4. …… 5. } 6. }; 7. public Singleton3 getInstance(){ 8. return INSTANCE; 9. } 10. public abstract void doSomet
9、hing(); 11. } Singleton单类模式中只有一个INSTANCE枚举元素,枚举可以保证真个程序生命周期中只有一个实例对象存在,同时还避免了常规Singleton单类模式private构造方法被反射调用和序列化问题。 注意:java中除了构造方法可以创建对象实例以外,还可以通过克隆方法(clone()是Object中的protected方法)来创建对象, 若单类对象直接继承自Object对象,则如果没有提供具体clone方法实现,则当调用克隆方法创建对象时,会抛出运行时的异常 CloneNotSupportedException。 若单类类继承了实现克隆方法的
10、类,则在单类类中必须覆盖父类的克隆方法,显式抛出异常CloneNotSupportedException。 另外,实现了单类模式的类不能再有派生子类,因为构造方式是私有的,子类无法调用父类构造方法,因此达到了Final的效果。 Proxy设计模式 Proxy代理设计模式是一种控制对象访问的设计模式,类似于网络代理,网络代理机制如下图: Proxy代理设计模式机制如下: 客户端程序通过代理程序来访问真正的目标程序,代理程序对外隐藏了目标程序。普通代理设计模式例子代码如下: [java] view plaincopy 1. interface ProxyBase{ 2
11、 public void f(); 3. public void g(); 4. public void h(); 5. } 6. //代理程序 7. class Proxy implement ProxyBase{ 8. private ProxyBase implementation; 9. public Proxy(){ 10. //目标程序 11. implementation = new ProxyImplementation(); 12. }
12、 13. public void f(){ 14. implementation.f(); 15. } 16. public void g(){ 17. implementation.g(); 18. } 19. public void h(){ 20. implementation.h(); 21. } 22. } 23. //目标程序 24. class ProxyImplementation implements Prox
13、yBase{ 25. public void f(){ 26. System.out.println(“ProxyImplementation.f()”); 27. } 28. public void g(){ 29. System.out.println(“ProxyImplementation.g()”); 30. } 31. public void h(){ 32. System.out.println(“ProxyImplementation.h()”
14、); 33. } 34. } 35. //客户端程序调用代理 36. public class ProxyDemo{ 37. public static void main(String[] args){ 38. //客户端调用代理程序 39. Proxy p = new Proxy(); 40. p.f(); 41. p.g(); 42. p.h(); 43. } 44. } 从JDK1.3以后,java引入动态
15、代理机制,java的动态代理只能针对接口进行动态代理,即要实现动态代理的类必须实现接口,CGLIB提供了针对类的动态代理功能。JDK动态代理的例子如下: [java] view plaincopy 1. //代理接口 2. interface Foo{ 3. public void f(String s); 4. public void g(int i); 5. public void h(int i, String s); 6. } 7. //接口实现类,即被代理类 8. class FooImpl implements
16、Foo{ 9. public void f(String s){ 10. System.out.println(“FooImpl.f(), s=” + s); 11. } 12. public void g(int i) { 13. System.out.println(“FooImpl.g(), i=” + i); 14. } 15. public void h(int i, String s) { 16. System.out.println(“FooIm
17、pl.h(), i=” + i + “, s=” + s); 17. } 18. } 19. //动态代理处理类 20. class ProxyHandler implements InvocationHandler{ 21. //代理实现类 22. private Object delegate; 23. public ProxyHandler (Object obj) { 24. delegate = obj; 25.
18、 } 26. public Object invoke(Object proxy, Method method, Object[] args){ 27. System.out.println(“Before mothod:” + method); 28. method.invoke(this.delegate, args); 29. System.out.println(“After mothod:” + method); 30. return null; 31.
19、} 32. } 33. public class DynamicProxyDemo{ 34. public static void main(String[] args){ 35. Foo foo = new FooImpl(); 36. ProxyHandler handler = new ProxyHandler(foo); 37. //产生动态代理 38. Foo proxy = (Foo)Proxy.newProxyInstance(Foo.class.getClassLoader
20、), new Class[]{Foo.class}, handler); 39. proxy.f(“f”); 40. proxy.g(1); 41. proxy.h(“h”, 2); 42. } 43. } 动态代理和普通的代理模式的区别:动态代理中的代理类是由java.lang.reflect.Proxy类在运行期时根据接口定义,采用Java 反射功能动态生成的。和java.lang.reflect.InvocationHandler结合,可以加强现有类的方法实现。动态带来自定义 Handler实现
21、InvocationHandler接口,自定义Handler实例化时,将代理的实现类传入自定义Handler对象中。自定义 Handler需要实现invoke方法,该方法可以使用Java反射调用实现类的实现的方法,同时当然可以实现其他功能,例如在调用实现类方法前后加入 Log,实现安全认证等。而Proxy类根据Handler和需要代理的接口动态生成一个接口实现类的对象。当用户调用这个动态生成的实现类时,实际上是 调用了自定义Handler的invoke方法。 State设计模式 State状态设计模式类似于Switch多路分支功能的开关,State状态模式机制如下: State状态
22、设计模式用于改变对象的行为,在代理的生命周期里,随着状态变化从一个目标实现程序切换到另一个目标实现程序。 我们经常遇到如下的程序代码: [java] view plaincopy 1. public class Creature{ 2. private Boolean isFrog = true;//标识 3. public void greet(){ 4. if(isForg){ 5. System.out.println(“Ribbet!”); 6. }else{ 7.
23、 System.out.println(“Darling!”); 8. } 9. } 10. //转换标识 11. public void kiss(){ 12. isForg = false; 13. } 14. public static void main(String[] args){ 15. Creature creature = new Creature(); 16. creature.greet();
24、 17. creature.kiss(); 18. creature.greet(); 19. } 20. } 上面例子代码中greet()方法在执行具体操作之前必须要判断一下标识,代码显得笨拙繁琐,使用简单State状态模式改写上面代码如下: [java] view plaincopy 1. public class Creature{ 2. //状态接口 3. private interface State{ 4. String response();
25、 5. } 6. private class Forg implements State{ 7. public String response(){ 8. return “Ribbet!”; 9. } 10. } 11. private class Prince implements State{ 12. public String response(){ 13. return “Darling!”; 14.
26、 } 15. } 16. private State state = new Forg(); 17. public void greet(){ 18. System.out.println(state.response); 19. } 20. public void kiss(){ 21. state = new Prince(); 22. } 23. public static void main(String[] args){
27、 24. Creature creature = new Creature(); 25. creature.greet(); 26. creature.kiss(); 27. creature.greet(); 28. } 29. } State状态设计模式中,状态自动切换并传播,不需要再改动标识,代码显得非常优雅。 State状态设计模式一个基本框架如下: [java] view plaincopy 1. //状态接口 2. interface Stat
28、e{ 3. void operation1(); 4. void operation2(); 5. void operation3(); 6. } 7. //状态实现类1 8. class implementation1 implements State{ 9. public void operation1(){ 10. System.out.println(“Implementation1.operation1()”); 11. } 12. public void op
29、eration2(){ 13. System.out.println(“Implementation1.operation2()”); 14. } 15. public void operation3(){ 16. System.out.println(“Implementation1.operation3()”); 17. } 18. } 19. //状态实现类2 20. class implementation2 implements State{ 21. public vo
30、id operation1(){ 22. System.out.println(“Implementation2.operation1()”); 23. } 24. public void operation2(){ 25. System.out.println(“Implementation2.operation2()”); 26. } 27. public void operation3(){ 28. System.out.println(“Implementation2
31、operation3()”); 29. } 30. } 31. //服务提供者 32. class ServiceProvider{ 33. private State state; 34. public ServiceProvider(State state){ 35. this.state = state; 36. } 37. //状态更改 38. public void changeState(State newState){ 39. s
32、tate = newState; 40. } 41. public void service1(){ 42. //…… 43. state.operation1(); 44. //…… 45. state.operation3(); 46. } 47. public void service2(){ 48. //…… 49. state.operation1(); 50.
33、 //…… 51. state.operation2(); 52. } 53. public void service3(){ 54. //…… 55. state.operation3(); 56. //…… 57. state.operation2(); 58. } 59. } 60. public class StateDemo{ 61. private ServiceProvid
34、er sp = new ServiceProvider(new Implementation1()); 62. private void run(ServiceProvider sp){ 63. sp.service1(); 64. sp.service2(); 65. sp.service3(); 66. } 67. public static void main(String[] args){ 68. StateDemo demo = new StateD
35、emo(); 69. demo.run(sp); 70. sp.changeState(new Implementation2()); 71. demo.run(sp); 72. } 73. } State状态模式和Proxy代理模式都为客户端程序提供了一个目标程序代理,真正的目标程序被代理所隐藏,当客户端程序调用目标程序时,首先将调用请求发送给代理,代理才真正调用目标程序,但是Proxy代理模式和State状态模式有如下区别: (1).Pro xy代理模式中被调用的目标程序只有一个,而State状态
36、模式中被调用的目标程序有多个。 (2).Proxy代理模式的目的是控制客户端对目标程序的访问,而State状态模式是为了根据条件动态改变目标程序。 Itrator设计模式 Iterator迭代器模式,提供一种统一的方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节,迭代器模式是为容器而设计。 程序对容器对象的访问必然涉及到遍历算法,不同的容器遍历算法是不同的,List,Stack和Set等等常用容器遍历元素的算法各不相同。解决容 器遍历算法差异有两种方案:第一,可以将遍历方法塞到容器对象中去,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(
37、添加、删除等等),而 且还要提供遍历自身的接口;第二,根本不提供容器遍历算法,让容器使用者自己去实现。该方法虽然是省事,却又将容器的内部细节暴露无遗。 迭代器模式的出 现,很好的解决了上面两种情况的弊端,不但将遍历容器的算法从不同集合容器类中抽象出来,同时又对外隐藏了容器的具体实现细节。 迭代器模式由以下角色组成: 1) 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。 2) 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。 3) 容器角色(Container):容器角色负责提供创建具体迭代器
38、角色的接口。 4) 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。 Java集合框架中迭代设计模式的应用: [java] view plaincopy 1. //迭代器 ,该接口提供了迭代遍历的通用方法 2. public interface Iterator { 3. boolean hasNext(); 4. Object next(); 5. void remove(); 6. } 7. //容器迭代化接口
39、凡是实现此接口的集合容器距可以生成相应的迭代器
8. public interface Iterable
40、码如下: [java] view plaincopy 1. public class MyIterator implements Iterable { 2. //存放数据的集合 3. private ArrayList list; 4. //负责创建具体迭代器角色的工厂方法 5. public Iterator iterator() { 6. return new Itr(list); 7. } 8. //作为内部类的具体迭代器角色 9. p
41、rivate class Itr implements Iterator { 10. ArrayList myList; 11. int position = 0; 12. public Itr(ArrayList list) { 13. this.myList = list; 14. } 15. public Object next() { 16. Object
42、 obj = myList.get(position); 17. position++; 18. return obj; 19. } 20. public boolean hasNext() { 21. if (position >= myList.size()) { 22. return false; 23. } e
43、lse { 24. return true; 25. } 26. } 27. //不支持remove操作 28. public void remove(){ 29. throw new UnsupportedOperationException( 30. "Alternating MyIterator does not support remove()");
44、 31. } 32. } 33. } 使用时,MyIterator对象直接调用iterator()方法就可以将自定义容器对象转换为迭代器对象。 Iterator模式的优点: (1).实现功能分离,简化容器接口。让容器只实现本身的基本功能,把迭代功能委让给外部类实现,符合类的设计原则。 (2).隐藏容器的实现细节。 (3).为容器或其子容器提供了一个统一接口,一方面方便调用;另一方面使得调用者不必关注迭代器的实现细节。 (4).可以为容器或其子容器实现不同的迭代方法或多个迭代方法。 Strategy设计模式 Strategy策略设计模式主要是定义一系列的算
45、法,把这些算法封装成单独的类,在运行时动态选择需要的算法,策略模式机制如下: 策略模式例子如下: [java] view plaincopy 1. //文本替换策略 2. abstract class TextStrategy { 3. protected String text; 4. 5. public TextStrategy(String text) { 6. this.text = text; 7. } 8. public abstract String replace();
46、 9. } 10. //替换算法1:将文本中"@r@n"替换为"@n" 11. class StrategyOne extends TextStrategy { 12. public StrategyOne(String text) { 13. super(text); 14. } 15. public String replace() { 16. System.out.println(“StrategyOne:”); 17. String result =
47、 text.replaceAll("@r@n", "@n")); 18. return result; 19. } 20. } 21. //替换算法2:将文本中"@n"替换为"@r@n" 22. class StrategyTwo extends TextStrategy { 23. public StrategyTwo(String text) { 24. super(text); 25. } 26. public String replace() {
48、27. System.out.println(“StrategyTwo:”); 28. String result = text.replaceAll(“@n", "@r@n")); 29. return result; 30. } 31. } 32. public class TextCharChange { 33. public static void replace(TextStrategy strategy) { 34. strategy.replace
49、); 35. } 36. public static void main(String[] args){ 37. String testText1 = "This is a test text!!@n Oh! Line Return!!@n"; 38. String testText2 = This is a test text!!@r@n Oh! Line Return@r@n"; 39. TextCharChange.replace(new StrategyOne(testText2)); 40. Te
50、xtCharChange.replace(new StrategyTwo(testText1)); 41. } 42. } State状态模式和Strategy策略模式非常类似,但是有如下区别: (1).State状态模式重点在于设定状态变化,根据状态,返回相应的响应。 (2).Strategy策略模式重点在于根据需求直接采用设定的策略,即根据场景选择合适的处理算法,而不需要改变状态。 Factory设计模式 Factory工厂设计模式为创建对象提供了一种抽象,而对使用者屏蔽了对象创建的具体细节过程,工厂模式有三种:简单工厂模式,抽象工厂模式和工厂方法模式。 (






