设计模式学习(1)

关于设计模式的理解与介绍已经有很多大牛写出了非常优秀的文章,所以仅在此记录自己的学习过程与总结。

这是我参考学习的一个系列博客http://www.cnblogs.com/justinw/archive/2006/11/28/574573.html,在此对博主表示衷心的感谢!

参考书籍《HeadFirst设计模式》。

废话不多说了,进入正题:

一、比模式更重要的是设计原则

1、找到系统中变化的部分,将变化的部分同其它稳定的部分隔开;

2、面向接口编程,而不要面向实现编程;

3、优先使用对象组合,而非类继承;

4、类应该对扩展开放,对修改关闭;

5、单一责任:一个类应该只有一个引起变化的原因;

二、设计模式

1、策略模式

设计模式学习(1)_第1张图片

Context(应用场景):

        需要使用ConcreteStrategy提供的算法。

        内部维护一个Strategy的实例。

        负责动态设置运行时Strategy具体的实现算法。

        负责跟Strategy之间的交互和数据传递。

Strategy(抽象策略类):

        定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或抽象类实现。

ConcreteStrategy(具体策略类):

        实现了Strategy定义的接口,提供具体的算法实现

总结:策略模式使用在这样的场景中,B是A的一部分,但B可能有多种不同的实现方式,如果不加处理,那么之后如果B增加了实现,那么就要重新写一个A类来实现这个不同的B,随着扩展的加深,我们就会看到自己的包里有A1.java、A2.java……像这样的文件就会越来越多。而策略模式就是先将B抽象出来,使得A只需要包含一个B的抽象,待到具体应用时再将A中的B实例化,而B的实现则可以在A之外随意扩展。

就像三国演义里诸葛亮给赵云的锦囊妙计一样,为了保护要去吴国的刘备,诸葛亮在临走前给了赵云三个锦囊,说在危急的时刻拿出来看一下便可化险为夷。这里即可看做是一个策略模式。对赵云来说,给他的计策是变化的,诸葛亮要把计策教给赵云,最简单的就是在临走前把计策都给赵云说一遍,这样就会有知道计策一的赵云、知道计策二的赵云等等,要是计策多了那诸葛亮可能就得说上个一两天,这么做还有个问题,就是如果诸葛亮哪天有个新想法他都要和赵云说一遍,如果情况有变有一些计策不用了那他就白费口舌了。不科学!所以诸葛亮想到了用锦囊,对赵云来说这个锦囊就是个抽象,他不需要知道具体细节,只需要知道怎么打开锦囊看内容就可以了,而这里就只有一个知道怎么打开锦囊的赵云,于是诸葛亮为赵云准备了三个锦囊,到了吴国,赵云眼看情况不对,拿出第一个锦囊,这里就相当于将锦囊实例化了,然后赵云打开锦囊读内容,这里就相当于实例化了一个知道计策一的赵云,之后赵云执行计策内容,大功告成!

所以这里赵云 = Context,锦囊 = Strategy,(锦囊一、二、三)= ConcreteStrategy。


2、观察者模式

观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新
设计模式学习(1)_第2张图片
Subject(被观察的对象接口)  

         规定ConcreteSubject的统一接口;

         每个Subject可以有多个Observer;

ConcreteSubject(具体被观察对象)

         维护对所有具体观察者的引用的列表;

         状态发生变化时会发送通知给所有注册的观察者。

Observer(观察者接口)

         规定ConcreteObserver的统一接口;

         定义了一个update()方法,在被观察对象状态改变时会被调用。

ConcreteObserver(具体观察者)

         维护一个对ConcreteSubject的引用;

         特定状态与ConcreteSubject同步;

         实现Observer接口,通过update()方法接收ConcreteSubject的通知。

总结:观察者模式可以看做是现实中的报纸订阅模式,客户是观察者(Observer),报社是被观察者(Subject),客户要看报纸了解各种新闻事件,就首先要向报社订阅要看的报纸,这样只要出了新报纸,报社就会把报纸送到客户手上。
结合上边的类图,举例来说,张三是一名具体的客户(Concrete Observer),要看《程序员》,张三实现了一个自己的update()方法,也就是当出版社把新出的《程序员》送过来后要怎么处理(当然是拿着读咯,至于是坐着读还是躺着读那就看个人爱好了)。要看《程序员》,首先要向出版社(Concrete Subject)订阅啊,出版社有自己的一套管理体系,也就是那三个基本的方法(注册、移除、通知),张三怎么订阅呢,首先找到出版社(代码里就是实例化出版社!),然后用出版社的注册方法把自己的一个引用传过去,相当于给了一个名片。有新一期的《程序员》啦,出版社开始通知订阅者,也就是把杂志送到订阅者手上(代码里就是挨个调用订阅者的update方法!),大功告成。

3、装饰者模式

装饰者模式可以动态地给一个对象增加其他职责。就扩展对象功能来说,装饰者模式比生成子类更为灵活。
设计模式学习(1)_第3张图片

Component(被装饰对象基类)  
     定义对象的接口,可以给这些对象动态增加职责;
ConcreteComponent(具体被装饰对象)
        定义具体的对象,Decorator可以给它增加额外的职责;
    Decorator(装饰者抽象类)
        维护一个指向Component实例的引用,并且定义了与Component一致的接口;
    ConcreteDecorator(具体装饰者)
        具体的装饰对象,给内部持有的具体被装饰对象增加具体的职责;


总结:装饰者模式主要用于灵活扩展类对象的功能,而不需要通过继承来实现。该模式的核心部分在装饰者(Decorator),他继承自Component(被装饰对象),同时还包含了一个Component的引用,这么做使得装饰者的本质不发生变化,可以继续被装饰,也就是说装饰者同时可以做为被装饰者。举个例子,咖啡是一个被装饰者,是一个基类(Component),黑咖啡是他的一种具体对象(Concrete Component)。现在我们想给黑咖啡装饰一下,加些牛奶,得到加牛奶的黑咖啡。关键就在这里,加了牛奶的黑咖啡的依然是咖啡,也就是他的本质没有变化,这样就可以继续进行装饰,比如加糖变成加糖加牛奶的黑咖啡。具体做法就像上面的类图展示的,先定义一个装饰者抽象类(Decorator)--咖啡装饰类;然后继承得到具体的装饰类(Concrete Decorator)--加牛奶咖啡装饰类,加糖咖啡装饰类。这样只要将咖啡类的实例作为参数传入装饰者,就可以得到装饰了的对象,大功告成!装饰者的一个典型的应用即是java中的I/O类的应用,inputstream、outputstream。




你可能感兴趣的:(设计模式学习(1))