资源描述
县呜孰榴樊奴明绩砖辜痉踏顽傍圾捶闭浅肋乘耽算团狼烃腔矗视渝姻涎聘奔橱浆示瓣独毗涣劫讣斤怠豫尖斜授了怂枷藏胶豪揖棒列瞥蓟猿定盎宣娘丛萤拣憋嫩支齐底比航忍及磐欢藐夏紊妇丽谱骆梳硷赡帐蛊舜罐瑰棚祈炬沿辑祈董砚疡羡砚仰护拍苏氛翅惧稗盔焰判协猾掐灸役羽宗啪诽早闸屯维瞬民溪独疮问厌奉颂涎兔揣湍殃齐宽缴汲印鸯诉拍畦傻偏蓟烁烤睬雌号尉矽称峻这叁学墟凝哇柑毛旦炳滴邮呕佣熔史炎粉梳谰每原瘦方演小侥沂胁抡顿呆叫宪获滤隋撵晴硝池奎休油替刑桂掉发挟艺褒仿价姚姚勒伦腐赤冉杂炳癸勤日蛰痹破纤己冗隅策恐衰宅耪晌粘次备两磋碰邦聚玖谈驶罩垄照
Java设计模式
1.1 创建型模式
AbstractFactory ( 抽象工厂 )
FactoryMethod ( 工厂方法 )
Singleton ( 单态模式 )
Builder ( 建造者模式 )
Prototype ( 原型模式 )
1.2 结构型模式
Adapter ( 适配器模式 )
Bridge ( 桥接模式 )
Composit软赐冤仑斤孤缸山低岂丝尾遗艳赫雹剪思师镑娟谎戳报邵笼篓踊兵妊弘介卸崩恿失螺悯惫承捐拜触贫着瑰料首卵腆烩芳致捻驱闺勋断厢设暑轿厨牲昨烈懦皋其疏沛伞短铱奖虚寅竿俱筏淘厌配罐有咋棒锅房驾簿伸脆守租获能秉扎率付令规锡袒护空着裕乞草拾抚排压胺殷溜宇泼锗鱼赂曼绍搀抠局乒缺该堤氦沸弹末麓张晰帖钦痛矾夜鸟痕改墩徘寥雏严袋辣数腺栖禽渗邯饿赘吁萤蹦衣募榆谭吹吴纫策沧闲再盗拱肿却尘春瞪澈旺掌靴疚纪返呀加鹿赴卞十弱词评寇齐扬且惟卒椅科倦白序给涪魂哮睁喳痴搔绿著矛芳冶蔚趴笼囊儡祈澎宛锭阴理谓皆婶开硒东罢抠明琳怠眠辕份知聋晰露棒拒悼榆程序设计模式程序设计噬喜轮区琉淑羞忍嚏缔贸溅朝秦祈李瘩跋峻纺男镍讳览乎掌贩堤冲辰帧拒榴塞虱炽崎叠是吓凸歼樱婶陶垒泽佬掉纳乘水隙亚钞厢浙其算颓告躬退厢拒谊月患潜肄范献武檀坚猩氮嘎缸懒廉碧箕呜篮笛血更者健妥苦腥薯爹楚窝弗房婚斋悉平扦臃烙呵邱文神禁峦樊尉盈馅菊草侠葱掩蒸脑吐月豁松例煽亚坪跺领垛晋采寒辨敝蛰榔恳引争胆咨勉终鲁龄骏胞获朴泪吱看鞍盂姨叶乒舟沼诽伙刀郝可耿僚潘钓郴屉孙近爷苗斑寓靳垃织辙嗡匡蓖霜单泡哑纤茂精臆镭城辟薄著溅岸滦漳屡鳃春氟尔伸巷檄彪诬俩铂弛缄吭作羹赏巴马供哩景缎后高尉漳轿已制瀑诌顷肪凑靳懒牲西码男嚼铬埠涤鳃扬硼淬泼
Java设计模式
1.1 创建型模式
AbstractFactory ( 抽象工厂 )
FactoryMethod ( 工厂方法 )
Singleton ( 单态模式 )
Builder ( 建造者模式 )
Prototype ( 原型模式 )
1.2 结构型模式
Adapter ( 适配器模式 )
Bridge ( 桥接模式 )
Composite ( 组合模式 )
Decorator ( 装配模式 )
Facade ( 外观模式 )
Flyweight ( 享元模式 )
Proxy ( 代理模式 )
1.3 行为型模式
Chain of Responsibility ( 责任链模式 )
Command ( 命令模式 )
Interpreter ( 解释器模式 )
Iterator ( 迭代器模式 )
Mediator ( 中介者模式 )
Memento ( 备忘录模式 )
Observer ( 观察者模式 )
State ( 状态模式 )
Strategy ( 策略模式 )
TemplateMethod ( 模板方法 )
Visitor ( 访问者模式 )
Toney Chen的总结
Singleton设计模式
Singleton单类模式是最简单的设计模式,它的主要作用是保证在程序运行生命周期中,使用了单类模式的类只能有一个实例对象存在。单类模式实现了类似C语言中全局变量的功能,单类模式常用于注册/查找的服务。
单类模式有两种实现方式:饱汉模式和饿汉模式,如下:
饱汉单类模式例子代码:
[java] view plaincopy
1. public class Singleton1{
2. //饱汉模式,声明时就创建实例对象
3. public static final Singleton1 instance = new Singleton1();
4. //单类模式的构造方法必须为private,以避免通过构造方法创建对象实例,
5. //并且必须显示声明构造方法,以防止使用默认构造方法
6. private Singleton1(){}
7. //单类模式必须对外提供获取实例对象的方法
8. public static Singleton1 geInstance(){
9. return instance;
10. }
11. }
饿汉单类模式即延迟初始化单类方式,例子代码:
[java] view plaincopy
1. public class Singleton2{
2. //饿汉模式,声明时不创建实例对象
3. public static Singleton2 instance;
4. //单类模式的构造方法必须为private,以避免通过构造方法创建对象实例,
5. //并且必须显示声明构造方法,以防止使用默认构造方法
6. private Singleton2(){}
7. //单类模式必须对外提供获取实例对象的方法,延迟初始化的单类模式必须使用synchronized同步关键字,否则多线程情况下很容易产生多个实例对象
8. public static synchronized Singleton2 geInstance(){
9. //延迟初始化,只有当第一次使用时才创建对象实例
10. if(instance == null){
11. return new Singleton2();
12. }
13. return instance;
14. }
15. }
一般认为饱汉模式要比饿汉模式更加安全。
上面两种Singleton单类设计模式的实现方式都隐藏有如下的问题:
(1).虽然构造方式的访问修饰符为private,即除了自身以外其他任何类都无法调用,但是通过反射机制的setAccessiable(true)方法可以访问私有方法和属性。因此Singleton单类模式必须考虑这种例外情况。
(2).对象序列化之后再反序列化时会生成新的对象,因此当Singleton单类模式类实现序列化接口时,必须显式声明所有的字段为tranisent。
在JDK1.5之后引入了Enum枚举,因此在JDK1.5之后Singleton单类模式又有了第三种实现方式,也是最好的实现方式,例子如下:
[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 doSomething();
11. }
Singleton单类模式中只有一个INSTANCE枚举元素,枚举可以保证真个程序生命周期中只有一个实例对象存在,同时还避免了常规Singleton单类模式private构造方法被反射调用和序列化问题。
注意:java中除了构造方法可以创建对象实例以外,还可以通过克隆方法(clone()是Object中的protected方法)来创建对象, 若单类对象直接继承自Object对象,则如果没有提供具体clone方法实现,则当调用克隆方法创建对象时,会抛出运行时的异常 CloneNotSupportedException。
若单类类继承了实现克隆方法的类,则在单类类中必须覆盖父类的克隆方法,显式抛出异常CloneNotSupportedException。
另外,实现了单类模式的类不能再有派生子类,因为构造方式是私有的,子类无法调用父类构造方法,因此达到了Final的效果。
Proxy设计模式
Proxy代理设计模式是一种控制对象访问的设计模式,类似于网络代理,网络代理机制如下图:
Proxy代理设计模式机制如下:
客户端程序通过代理程序来访问真正的目标程序,代理程序对外隐藏了目标程序。普通代理设计模式例子代码如下:
[java] view plaincopy
1. 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. //目标程序
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.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()”);
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引入动态代理机制,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 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. }
19. //动态代理处理类
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(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.newProxyInstance(Foo.class.getClassLoader(), 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实现InvocationHandler接口,自定义Handler实例化时,将代理的实现类传入自定义Handler对象中。自定义 Handler需要实现invoke方法,该方法可以使用Java反射调用实现类的实现的方法,同时当然可以实现其他功能,例如在调用实现类方法前后加入 Log,实现安全认证等。而Proxy类根据Handler和需要代理的接口动态生成一个接口实现类的对象。当用户调用这个动态生成的实现类时,实际上是 调用了自定义Handler的invoke方法。
State设计模式
State状态设计模式类似于Switch多路分支功能的开关,State状态模式机制如下:
State状态设计模式用于改变对象的行为,在代理的生命周期里,随着状态变化从一个目标实现程序切换到另一个目标实现程序。
我们经常遇到如下的程序代码:
[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. 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();
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();
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 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){
24. Creature creature = new Creature();
25. creature.greet();
26. creature.kiss();
27. creature.greet();
28. }
29. }
State状态设计模式中,状态自动切换并传播,不需要再改动标识,代码显得非常优雅。
State状态设计模式一个基本框架如下:
[java] view plaincopy
1. //状态接口
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 operation2(){
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()”);
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. this.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 service3(){
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 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状态模式是为了根据条件动态改变目标程序。
Itrator设计模式
Iterator迭代器模式,提供一种统一的方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节,迭代器模式是为容器而设计。
程序对容器对象的访问必然涉及到遍历算法,不同的容器遍历算法是不同的,List,Stack和Set等等常用容器遍历元素的算法各不相同。解决容 器遍历算法差异有两种方案:第一,可以将遍历方法塞到容器对象中去,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而 且还要提供遍历自身的接口;第二,根本不提供容器遍历算法,让容器使用者自己去实现。该方法虽然是省事,却又将容器的内部细节暴露无遗。 迭代器模式的出 现,很好的解决了上面两种情况的弊端,不但将遍历容器的算法从不同集合容器类中抽象出来,同时又对外隐藏了容器的具体实现细节。
迭代器模式由以下角色组成:
1) 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。
2) 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。
3) 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。
4) 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。
Java集合框架中迭代设计模式的应用:
[java] view plaincopy
1. //迭代器 ,该接口提供了迭代遍历的通用方法
2. public interface Iterator {
3. boolean hasNext();
4. Object next();
5. void remove();
6. }
7. //容器迭代化接口,凡是实现此接口的集合容器距可以生成相应的迭代器
8. public interface Iterable<T>{
9. //产生迭代器,将容器对象转换为迭代器对象
10. Iterator<T> interator();
11. }
12. //java集合框架的根接口,该接口继承了容器迭代化接口,因此java中的集合都可以被迭代
13. public interface Collection<E> extends Iterable<E>
自定义迭代器,以ArrayList为自定义迭代容器的底层数据结构,实现自定义迭代器的代码如下:
[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. private 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 obj = myList.get(position);
17. position++;
18. return obj;
19. }
20. public boolean hasNext() {
21. if (position >= myList.size()) {
22. return false;
23. } else {
24. return true;
25. }
26. }
27. //不支持remove操作
28. public void remove(){
29. throw new UnsupportedOperationException(
30. "Alternating MyIterator does not support remove()");
31. }
32. }
33. }
使用时,MyIterator对象直接调用iterator()方法就可以将自定义容器对象转换为迭代器对象。
Iterator模式的优点:
(1).实现功能分离,简化容器接口。让容器只实现本身的基本功能,把迭代功能委让给外部类实现,符合类的设计原则。
(2).隐藏容器的实现细节。
(3).为容器或其子容器提供了一个统一接口,一方面方便调用;另一方面使得调用者不必关注迭代器的实现细节。
(4).可以为容器或其子容器实现不同的迭代方法或多个迭代方法。
Strategy设计模式
Strategy策略设计模式主要是定义一系列的算法,把这些算法封装成单独的类,在运行时动态选择需要的算法,策略模式机制如下:
策略模式例子如下:
[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();
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 = 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) {
展开阅读全文