1、Java 设计模式1.1 创建型模式AbstractFactory ( 抽象工厂 ) FactoryMethod ( 工厂方法 ) Singleton ( 单态模式 ) Builder ( 建造者模式 ) Prototype ( 原型模式 ) 1.2 结构型模式Adapter ( 适配器模式 ) Bridge ( 桥接模式 ) Composite ( 组合模式 ) Decorator ( 装配模式 ) Facade ( 外观模式 ) Flyweight ( 享元模式 ) Proxy ( 代理模式 ) 1.3 行为型模式Chain of Responsibility ( 责任链模式 ) Comm
2、and ( 命令模式 ) Interpreter ( 解释器模式 ) Iterator ( 迭代器模式 ) Mediator ( 中介者模式 ) Memento ( 备忘录模式 ) Observer ( 观察者模式 ) State ( 状态模式 ) Strategy ( 策略模式 ) TemplateMethod ( 模板方法 ) Visitor ( 访问者模式 ) Toney Chen 的总结Singleton 设计模式 Singleton 单类模式是最简单的设计模式,它的主要作用是保证在程序运行生命周期中,使用了单类模式的类只能有一个实例对象存在。单类模式实现了类似 C 语言中全局变量的功
3、能,单类模式常用于注册/查找的服务。单类模式有两种实现方式:饱汉模式和饿汉模式,如下:饱汉单类模式例子代码:java view plaincopy1. public class Singleton1 2. /饱汉模式,声明时就创建实例对象 3. public static final Singleton1 instance = new Singleton1(); 4. /单类模式的构造方法必须为 private,以避免通过构造方法创建对象实例, 5. /并且必须显示声明构造方法,以防止使用默认构造方法 6. private Singleton1() 7. /单类模式必须对外提供获取实例对象的方
4、法 8. public static Singleton1 geInstance() 9. return instance; 10. 11. 饿汉单类模式即延迟初始化单类方式,例子代码:java view plaincopy1. public class Singleton2 2. /饿汉模式,声明时不创建实例对象 3. public static Singleton2 instance; 4. /单类模式的构造方法必须为 private,以避免通过构造方法创建对象实例, 5. /并且必须显示声明构造方法,以防止使用默认构造方法 6. private Singleton2() 7. /单类模式
5、必须对外提供获取实例对象的方法,延迟初始化的单类模式必须使用 synchronized 同步关键字,否则多线程情况下很容易产生多个实例对象 8. public static synchronized Singleton2 geInstance() 9. /延迟初始化,只有当第一次使用时才创建对象实例 10. if(instance = null) 11. return new Singleton2(); 12. 13. return instance; 14. 15. 一般认为饱汉模式要比饿汉模式更加安全。上面两种 Singleton 单类设计模式的实现方式都隐藏有如下的问题:(1).虽然构造
6、方式的访问修饰符为 private,即除了自身以外其他任何类都无法调用,但是通过反射机制的 setAccessiable(true)方法可以访问私有方法和属性。因此 Singleton 单类模式必须考虑这种例外情况。(2).对象序列化之后再反序列化时会生成新的对象,因此当 Singleton 单类模式类实现序列化接口时,必须显式声明所有的字段为 tranisent。在 JDK1.5 之后引入了 Enum 枚举,因此在 JDK1.5 之后 Singleton 单类模式又有了第三种实现方式,也是最好的实现方式,例子如下:java view plaincopy1. public enum Singl
7、eton3 2. INSTANCE 3. public void doSomething() 4. 5. 6. ; 7. public Singleton3 getInstance() 8. return INSTANCE; 9. 10. public abstract void doSomething(); 11. Singleton 单类模式中只有一个 INSTANCE 枚举元素,枚举可以保证真个程序生命周期中只有一个实例对象存在,同时还避免了常规 Singleton 单类模式 private 构造方法被反射调用和序列化问题。注意:java 中除了构造方法可以创建对象实例以外,还可以通过克
8、隆方法(clone()是 Object 中的 protected 方法)来创建对象, 若单类对象直接继承自Object 对象,则如果没有提供具体 clone 方法实现,则当调用克隆方法创建对象时,会抛出运行时的异常 CloneNotSupportedException。若单类类继承了实现克隆方法的类,则在单类类中必须覆盖父类的克隆方法,显式抛出异常 CloneNotSupportedException。另外,实现了单类模式的类不能再有派生子类,因为构造方式是私有的,子类无法调用父类构造方法,因此达到了 Final 的效果。Proxy 设计模式 Proxy 代理设计模式是一种控制对象访问的设计模
9、式,类似于网络代理,网络代理机制如下图:Proxy 代理设计模式机制如下:客户端程序通过代理程序来访问真正的目标程序,代理程序对外隐藏了目标程序。普通代理设计模式例子代码如下:java view plaincopy1. interface ProxyBase 2. 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. /目标程
10、序 11. implementation = new ProxyImplementation(); 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 ProxyBase 25. public void f() 26. System.out.pr
11、intln(“ProxyImplementation.f()”); 27. 28. public void g() 29. System.out.println(“ProxyImplementation.g()”); 30. 31. public void h() 32. System.out.println(“ProxyImplementation.h()”); 33. 34. 35. /客户端程序调用代理 36. public class ProxyDemo 37. public static void main(String args) 38. /客户端调用代理程序 39. Proxy
12、p = new Proxy(); 40. p.f(); 41. p.g(); 42. p.h(); 43. 44. 从 JDK1.3 以后,java 引入动态代理机制,java 的动态代理只能针对接口进行动态代理,即要实现动态代理的类必须实现接口,CGLIB 提供了针对类的动态代理功能。JDK 动态代理的例子如下:java view plaincopy1. /代理接口 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. /接口
13、实现类,即被代理类 8. class FooImpl implements 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(“FooImpl.h(), i=” + i + “, s=” + s); 17. 18. 1
14、9. /动态代理处理类 20. class ProxyHandler implements InvocationHandler 21. /代理实现类 22. private Object delegate; 23. public ProxyHandler (Object obj) 24. delegate = obj; 25. 26. public Object invoke(Object proxy, Method method, Object args) 27. System.out.println(“Before mothod:” + method); 28. method.invoke
15、(this.delegate, args); 29. System.out.println(“After mothod:” + method); 30. return null; 31. 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.newProxyI
16、nstance(Foo.class.getClassLoader(), new ClassFoo.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 实现 InvocationHandle
17、r 接口,自定义Handler 实例化时,将代理的实现类传入自定义 Handler 对象中。自定义 Handler 需要实现 invoke 方法,该方法可以使用 Java 反射调用实现类的实现的方法,同时当然可以实现其他功能,例如在调用实现类方法前后加入 Log,实现安全认证等。而 Proxy 类根据 Handler 和需要代理的接口动态生成一个接口实现类的对象。当用户调用这个动态生成的实现类时,实际上是 调用了自定义 Handler 的 invoke 方法。State 设计模式 State 状态设计模式类似于 Switch 多路分支功能的开关,State 状态模式机制如下:State 状态设
18、计模式用于改变对象的行为,在代理的生命周期里,随着状态变化从一个目标实现程序切换到另一个目标实现程序。我们经常遇到如下的程序代码:java view plaincopy1. public class Creature 2. private Boolean isFrog = true;/标识 3. public void greet() 4. if(isForg) 5. System.out.println(“Ribbet!”); 6. else 7. System.out.println(“Darling!”); 8. 9. 10. /转换标识 11. public void kiss() 1
19、2. isForg = false; 13. 14. public static void main(String args) 15. Creature creature = new Creature(); 16. creature.greet(); 17. creature.kiss(); 18. creature.greet(); 19. 20. 上面例子代码中 greet()方法在执行具体操作之前必须要判断一下标识,代码显得笨拙繁琐,使用简单 State 状态模式改写上面代码如下:java view plaincopy1. public class Creature 2. /状态接口 3
20、. private interface State 4. String response(); 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. 15. 16. private State state = new Forg(); 17. public voi
21、d greet() 18. System.out.println(state.response); 19. 20. public void kiss() 21. state = new Prince(); 22. 23. public static void main(String args) 24. Creature creature = new Creature(); 25. creature.greet(); 26. creature.kiss(); 27. creature.greet(); 28. 29. State 状态设计模式中,状态自动切换并传播,不需要再改动标识,代码显得非常
22、优雅。State 状态设计模式一个基本框架如下:java view plaincopy1. /状态接口 2. interface State 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
23、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 void operation1() 22. System.out.println(“Implementation2.operation1(
24、)”); 23. 24. public void operation2() 25. System.out.println(“Implementation2.operation2()”); 26. 27. public void operation3() 28. System.out.println(“Implementation2.operation3()”); 29. 30. 31. /服务提供者 32. class ServiceProvider 33. private State state; 34. public ServiceProvider(State state) 35. thi
25、s.state = state; 36. 37. /状态更改 38. public void changeState(State newState) 39. state = newState; 40. 41. public void service1() 42. / 43. state.operation1(); 44. / 45. state.operation3(); 46. 47. public void service2() 48. / 49. state.operation1(); 50. / 51. state.operation2(); 52. 53. public void s
26、ervice3() 54. / 55. state.operation3(); 56. / 57. state.operation2(); 58. 59. 60. public class StateDemo 61. private ServiceProvider sp = new ServiceProvider(new Implementation1(); 62. private void run(ServiceProvider sp) 63. sp.service1(); 64. sp.service2(); 65. sp.service3(); 66. 67. public static
27、 void main(String args) 68. StateDemo demo = new StateDemo(); 69. demo.run(sp); 70. sp.changeState(new Implementation2(); 71. demo.run(sp); 72. 73. State 状态模式和 Proxy 代理模式都为客户端程序提供了一个目标程序代理,真正的目标程序被代理所隐藏,当客户端程序调用目标程序时,首先将调用请求发送给代理,代理才真正调用目标程序,但是 Proxy 代理模式和 State 状态模式有如下区别:(1).Pro xy 代理模式中被调用的目标程序只有一个,而 State 状态模式中被调用的目标程序有多个。(2).Proxy 代理模式的目的是控制客户端对目标程序的访问,而 State 状态模式是为了根据条件动态改变目标程序。