部分设计模式介绍

设计模式的目的就是设计出弹性的、可复用的、可维护的系统;整本书放眼望去,其实都是用到了接口的概念;可能这也跟java中没有多继承有关吧;关于面向接口而不是面向对象这句话的理解在看了这么多设计模式之后,领悟到这其实是很简单的;在此将自己对于面向接口而非实现的理解写在下面:

  1. 首先我们手头上肯定有很多的各式各样的类,而且假设它们被使用了很多年,那就证明人家是很稳定的,或者我们压根就不想费劲的看它们底层如何实现,我们只是想在自己的新代码中使用他们;
  2. 然后呢我们在自己的客户代码中设想(期望)这些类要提供自己什么样的功能,我们把自己设想的这一堆功能写成一个接口;这样我们客户端的代码其实就写完了,我们只需要给它一个具体的实现了该接口的对象就可以工作了;所以说到这里也可以理解什么叫耦合了,而且这段代码具有可移植性;
  3. 接着呢我们现在去生成一个给客户代码使用的类,很明显这个类就需要对接口进行实现,这算是底层的操作了,这个类肯定是针对我们手头上的某一个已经存在的类而进行的,所以这个类的构造函数需要一个参数那就是老类的对象,新类对于接口的实现都是对老类对象的操作;
    至此整个面向接口的编程就结束了,它有什么好处呢?首先我们可以理想化的去编程客户端代码,而不需要考虑具体如何实现;第二这样的代码具有可扩展性,因为我们只需要新建一个实现了接口的类就可以使用原客户端代码,整个新建类的过程完全独立,而且原来的任何代码都不需要去修改!!

以下是一些个人觉得用的比较多的几个设计模式,特此进行简单的介绍,更多详细的介绍请参考《设计模式》;

策略模式(面向接口编程一个很好的例子)

定义:
    定义了算法族(针对了一个接口的不同实现方法的集群),将其进行封装,让他们可以相互替换,该模式让算法的变化独立于使用算法的客户;一个接口,多种实现;好比一个班的人,都具备一定的共同属性,但是每个人都个性十足;
实现:
    可以看成是只有一个状态的状态机模式;
与状态机模式的区别:
    策略模式,客户主动制定Context所要组合的策略对象是哪一个;策略模式被看成是一个除了继承之外的一种弹性替代方案(has-a);
    状态模式Context的客户对于状态对象了解不多,甚至根本不知道,状态都是各个状态自己在进行不断的转换,控制权在状态自己手上,这意味着对象拥有一组定义良好的状态转换;状态模式看成是不用在context中放置许多条件判断的替代方案;

观察者模式(1对多)

定义:
    定义了对象之间的一对多的依赖,这样一来,当一个对象(主题)的状态发生改变的时候,它的所有依赖者都会收到通知并自动更新;观察者模式是JDK中实用最多的模式之一;
实现:
    一、
    以包含Subject与Observer接口的类设计的做法最常见;主题实现接口Subject,其中定义了addObserver方法、removeObserver方法、setChange方法、notifyObserver方法;观察者实现接口Observer接口,其中定义update方法;
    二、
    使用java内置的观察者模式;即使用java.util包中的Observer接口和Observable类;使用内置的模式好处在于我们不需要编写addObserver方法、removeObserver方法、setChange方法、notifyObserver方法,我们需要进行的工作就是在主题类中合适的地方调用setChange方法、notifyObserver方法;在观察者类中定义自己的update方法和调用addObserver方法、removeObserver方法;但是坏处在于其通知的顺序没法保证;而且因为Observable是个类,所以会造成诸多不便(java不能多重继承,接口可以;而且与设计原则不符——少用继承);
具体流程:
    首先构造一个主题类,然后使用这个主题类去构造观察者类,观察者类利用主题类的addObserver方法自己注册为观察者(其实就是将自身这个对象放入主题类中的一个arraylist中去),随后一旦主题类有数据变化时它自己会调用setChange方法、notifyObserver方法(在该方法内部就是去调用arraylist中的每个观察者的update方法),随后观察者在update中进行相关的更新操作(更新操作有两种方式:第一就是主题把所有数据传给观察者,观察者处于被动接受;第二就是观察者调用主题的一个成员方法,主动的去获取自己感兴趣的数据);
总结
先有主题类,然后有观察者,上述过程完成之后,主题类中有观察者的引用,观察者中也有主题类的引用(不过它们成员变量都是通过接口来声明的);
Subject调用observer.update(); 用于通知更新;之后Observer在方法update中使用observer.xx = Subject.getxx();形式的代码从Subject中获取新数据;


装饰者模式(继承方法重写+组合模式)

定义:
    动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
实现:
    装饰者模式就是有一个明显的"主类"(类似一栋大楼的框架结构),和一些可有可无的装饰性的“辅类”(装修的建材);一个主类可以在其外部包裹很多个辅类;
    具体的java中具体实现就是主类和辅类的父类属于同一类的层次,它们都继承自一个抽象的超类。关系表示如下:father(抽象类)->class1,class2,....,classcrap; 然后classcrap(抽象类)->crap1,crap2,...;上面的father是抽象的超类,class1等是"主类",classcrap是“辅类”的父类,crap1等是辅类;在应用中我们用father来指向"主类"的对象,同样"主类"被辅类修饰后(形如:crap1(class1对象))(可以发现是利用class1对象生成了一个辅类对象)同样还是由father来指向;上一步之所以能够编译通过正是因为主类和辅助类继承自相同的超类;
some question:
    一、我们说少用继承但是从上面的实现可以发现我们使用了继承:此处使用继承仅仅为了达到“类型匹配”,而不是用继承获得方法,(在同名的方法下调用被装饰者的该同名方法,然后进行一下相关的处理,从而达到特定的目的。其实这有组合的味道不是吗?在装饰者的方法中,调用被装饰者的一个方法,进行特定的处理);
注意的地方:
    一、如果将代码(使用内了"主类"的一段程序)写成依赖于具体的组件类型(即上面的"主类"类型),那么装饰者将导致程序出问题,只有针对抽象组件类型编程时,才不会因为装饰者而受到影响;(该点还不太懂!!)(书中p99的内容,同下面的第四点一起进行考虑);(使用的场景)
    二、利用装饰者模式往往导致设计中有大量的小类,如果数量太多,可能造成此API程序员的困扰;(缺点)
    三、装饰者模式意味着一群装饰者类,这些类用来包装具体组件(即上面的"主类");
    四、装饰者一般对组件的客户是透明的(加不加装饰者,用户程序都是可以完全跟不加装饰者一样的使用组件),除非客户程序依赖于组件的具体类型;

单例模式(多线程处理情况)

定义:
     确保一个类只有一个实例,并且提供一个全局访问点;
实现:
  1. 声明一个可以指向类对象的private成员变量;如private volatile static ClassA instance;
  2. 将构造函数写成private形式;
  3. 写一个静态的成员方法用于返回第一步的变量(如果该变量还没有指向的对象就调用private构造函数后再返回);
  4. 为了使得多线程下也可以正常使用单件模式,可以采用P181提到的3种方法;不过建议还是使用第三种因为其兼顾了效率和安全;
  5. <span style="font-family:SimSun;">if(instance==null){
      synchronized(ClassA.class){
        if(instance==null){ instance = new ClassA();}
      }
    }
    return instance;</span>

reference:
《Head First 设计模式》Eric&Elisabeth(著)O'Reilly TaiWan公司(译)中国电力出版社;2007.9第一版,2010.7第七次印刷;









  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值