今天在准备腾讯的面试时想起来要复习一下设计模式,而刚好前几天在参加网易的在线考试的时候,也出了一道关于设计模式的选择题,主要是考察观察者模式,虽然那道题自己做对了,但觉得还是应该好好总结一下设计模式的内容。

一、设计模式的分类

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

二、设计模式的六大原则



1、开闭原则(Open Close Principle)

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。





2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。



4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。



5、迪米特法则(最少知道原则)(Demeter Principle)

最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。



6、合成复用原则(Composite Reuse Principle)

原则是尽量使用合成/聚合的方式,而不是使用继承。

三观察者模式

1 概述:

观察者模式(又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式),观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己,此种模式通常被用来实现事件处理系统,如java和安卓中的监听器。

2举例:

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知自动刷新。

3模式结构:

观察者模式的结构中包括四种角色:

 主题(Subject)

 观察者(Observer) 

 具体主题(ConcreteSubject) 

 具体观察者(ConcreteObserver)

4观察者模式的UML类图:



5观察者模式代码结构:(节选自百度百科)

  1. //抽象的观察者,需要用到观察者模式的类需实现此接口
  2. public interface Observer{
  3.     void update(Object...objs);
  4. }
  5.  
  6. //抽象的被观察者
  7. public abstract class Observable{
  8.  
  9.     public final ArrayList<Class<?>> obserList = new ArrayList<Class<?>>();
  10.  
  11.     /**AttachObserver(通过实例注册观察者)
  12.     *<b>Notice:</b>obcan'tbenull,oritwillthrowNullPointerException
  13.     **/
  14.     public<T> void registerObserver(Tob){
  15.         if(ob==null) throw new NullPointerException();
  16.         this.registerObserver(ob.getClass());
  17.     }
  18.  
  19.     /**
  20.     *AttachObserver(通过Class注册观察者)
  21.     *@paramcls
  22.     */
  23.     public void registerObserver(Class<?>cls){
  24.         if(cls==null) throw new NullPointerException();
  25.         synchronized(obserList){
  26.             if(!obserList.contains(cls)){
  27.                 obserList.add(cls);
  28.             }
  29.         }
  30.     }
  31.  
  32.     /**UnattachObserver(注销观察者)
  33.     *<b>Notice:</b>
  34.     *<b>ItreverseswithattachObserver()method</b>
  35.     **/
  36.     public<T>void unRegisterObserver(Tob){
  37.         if(ob==null) throw new NullPointerException();
  38.         this.unRegisterObserver(ob.getClass());
  39.     }
  40.  
  41.     /**UnattachObserver(注销观察者,有时候在未获取到实例使用)
  42.     *<b>Notice:</b>
  43.     *<b>ItreverseswithattachObserver()method</b>
  44.     **/
  45.     public void unRegisterObserver(Class<?>cls){
  46.         if(cls==null) throw new NullPointerException();
  47.         synchronized(obserList){
  48.             Iterator<Class<?>>iterator=obserList.iterator();
  49.             while(iterator.hasNext()){
  50.                 if(iterator.next().getName().equals(cls.getName())){
  51.                     iterator.remove();
  52.                     break;
  53.                 }
  54.             }
  55.         }
  56.     }
  57.  
  58.     /**detachallobservers*/
  59.     public void unRegisterAll(){
  60.         synchronized(obserList){
  61.             obserList.clear();
  62.         }
  63.     }
  64.  
  65.     /**Ruturnthesizeofobservers*/
  66.     public int countObservers(){
  67.         synchronized(obserList){
  68.             returnobserList.size();
  69.         }
  70.     }
  71.  
  72.     /**
  73.     *notify all observer(通知所有观察者,在子类中实现)
  74.     *@paramobjs
  75.     */
  76.     public abstract void notifyObservers(Object... objs);
  77.  
  78.     /**
  79.     *notify one certain observer(通知某一个确定的观察者)
  80.     *@paramcls
  81.     *@paramobjs
  82.     */
  83.     public abstract void notifyObserver(Class<?> cls, Object... objs);
  84.  
  85.     /**
  86.     *notifyonecertainobserver
  87.     *@paramcls
  88.     *@paramobjs
  89.     */
  90.     public abstract<T> void notifyObserver(T t, Object... objs);
  91. }
  92.  
  93. //目标被观察者
  94. public class ConcreteObservable extends Observable{
  95.  
  96.     private static ConcreteObservableinstance = null;
  97.     private ConcreteObservable(){};
  98.     public static synchronized ConcreteObservablegetInstance(){
  99.         if(instance == null){
  100.             instance=newConcreteObservable();
  101.         }
  102.         returninstance;
  103.     }
  104.  
  105.     @Override
  106.     public <T> void notifyObserver(T t, Object... objs){
  107.         if(== null) throw new NullPointerException();
  108.         this.notifyObserver(t.getClass(), objs);
  109.     }
  110.  
  111.     @Override
  112.     public void notifyObservers(Object... objs){
  113.         for(Class<?>cls : obserList){
  114.             this.notifyObserver(cls, objs);
  115.         }
  116.     }
  117.  
  118.  
  119.     //通过java反射机制实现调用
  120.     @Override
  121.     public void notifyObserver(Class<?>cls, Object...objs){
  122.         if(cls == null) throw new NullPointerException();
  123.         Method[] methods = cls.getDeclaredMethods();
  124.         for(Method method : methods){
  125.             if(method.getName().equals("update")){
  126.                 try{
  127.                     method.invoke(cls,objs);
  128.                     break;
  129.                 }catch(IllegalArgumentException e){
  130.                     e.printStackTrace();
  131.                 }catch(IllegalAccessException e){
  132.                     e.printStackTrace();
  133.                 }catch(InvocationTargetException e){
  134.                     e.printStackTrace();
  135.                 }
  136.             }
  137.         }
  138.     }
  139. }
  140.  
  141. //使用(实现Observer接口)
  142. public class Text extends Activity implements Observer{
  143.     publicvoidonCreate(...){
  144.         ConcreteObservable.getInstance().registerObserver(Text.class);
  145.         ....
  146.     }
  147.  
  148.     public void update(Object...objs){
  149.         //做操作,如更新数据,更新UI等
  150.     }
  151. }



【设计模式】java设计模式总述及观察者模式的更多相关文章

  1. Unity设计模式+Java设计模式,讲解+案例+PPT,一次性学会设计模式,拥抱高薪!

    一个程序员对设计模式的理解:“不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开一把锁的模式, ...

  2. 简单工厂设计模式--Java设计模式(一)

    一 概念: 简单工厂模式就是通过一个工厂类根据参数动态创建对应的类. 二 案例 我们以汽车作为例子,在现实生活中汽车只是一个抽象的产品,其中有很多类型的汽车才是具体产品,如奔驰.宝马.保时捷等等(当然 ...

  3. Java数据结构总述

    array list map set 链表..array 和list类似,增删慢,读取快,list长度可变,array长度固定, 链表增删快的list set 是一个没有重复数据的集合 map 是一个 ...

  4. Java设计模式学习资源汇总

    本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...

  5. Java设计模式知识整理

    1.Java设计模式     Java设计模式分为三种类型,分别是:      ①.创建型设计模式:是对对象创建过程的各种问题和解决方案的总结           包括:静态工厂模式.抽象工厂模式.单 ...

  6. Java设计模式学习笔记(一) 设计模式概述

    前言 大约在一年前学习过一段时间的设计模式,但是当时自己的学习方式比较低效,也没有深刻的去理解.运用所学的知识. 所以现在准备系统的再重新学习一遍,写一个关于设计模式的系列博客. 废话不多说,正文开始 ...

  7. 折腾Java设计模式之中介者模式

    博文原址:折腾Java设计模式之中介者模式 中介者模式 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并 ...

  8. java设计模式——建造者模式

    一. 定义与类型 定义:将一个复杂对象的构建与它的表示分离,使用同样的构建过程可以创建不同的表示 用户只需制定需要建造的类型就可以得到它们,建造过程以及细节不需要知道 类型:创建型 建造者模式与工厂模 ...

  9. Java 之设计模式(总述)

    1. 面向对象设计原则 单一职责原则: 一个类只负责一个功能领域中的相应职责 开闭原则: 软件实体应对扩展开放,而对修改关闭; 里氏代换原则: 所有引用基类对象的地方能够透明地使用其子类的对象; 依赖 ...

随机推荐

  1. 华科机考:a+b

    时间限制:1秒     空间限制:32768K 题目描述 实现一个加法器,使其能够输出a+b的值. 输入描述: 输入包括两个数a和b,其中a和b的位数不超过1000位. 输出描述: 可能有多组测试数据 ...

  2. Python中生成器和迭代器的功能介绍

    生成器和迭代器的功能介绍 1. 生成器(generator) 1. 赋值生成器 1. 创建 方法:x = (variable for variable in iterable) 例如:x = (i f ...

  3. 基于PHP的地址清洗调用案例-快宝开放平台

    快宝地址清洗,纠正错误地址.识别不完整地址.地址补全,并输出结构化地址数据的通用解决方案.广泛应用于快递行业,电商行业,ERP应用等. 快宝开放平台-地址清洗对接API:http://open.kua ...

  4. 46. Permutations(medium, backtrack, 重要)

    Given a collection of distinct numbers, return all possible permutations. For example, [1,2,3] have ...

  5. Web网页树形列表中实现选中父节点则子节点全选和不选中父则子全不选

                需要实现的功能:选中父节点对应子节点全选:不选中父节点,对应子节点也不选中 如下图所示,选中车队,对应车队中车辆也全部选中,以实现车队中所有车辆在地图上的显示. 选中cqupt ...

  6. grpc的服务注册与发现及负载

    参考文章: (1)https://segmentfault.com/a/1190000008672912 (2)https://grpc.io/docs/ (3)https://github.com/ ...

  7. python:浅析python 中__name__ = '__main__' 的作用(转载)

    每次看文章的源码时,Python的主程序中都会看到开头有这个,查了一下作用:https://www.cnblogs.com/alan-babyblog/p/5147770.html. 讲的很详细,就直 ...

  8. Docker常见仓库Ubuntu

    Ubuntu 基本信息 Ubuntu 是流行的 Linux 发行版,其自带软件版本往往较新一些. 该仓库提供了 Ubuntu从12.04 ~ 14.10 各个版本的镜像. 使用方法 默认会启动一个最小 ...

  9. Python3 解释器

    Linux/Unix的系统上,Python解释器通常被安装在 /usr/local/bin/python3.4 这样的有效路径(目录)里. 我们可以将路径 /usr/local/bin 添加到您的Li ...

  10. 安卓高级3 RecyclerView结合SwipeRefreshLayout并添加上拉

    目录结构: 效果图: MainActivity.java package qianfeng.com.pullrecyclerviewdemo; import android.os.Bundle; im ...