【设计模式】java设计模式总述及观察者模式
今天在准备腾讯的面试时想起来要复习一下设计模式,而刚好前几天在参加网易的在线考试的时候,也出了一道关于设计模式的选择题,主要是考察观察者模式,虽然那道题自己做对了,但觉得还是应该好好总结一下设计模式的内容。
一、设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
二、设计模式的六大原则
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观察者模式代码结构:(节选自百度百科)
//抽象的观察者,需要用到观察者模式的类需实现此接口
public interface Observer{
void update(Object...objs);
}
//抽象的被观察者
public abstract class Observable{
public final ArrayList<Class<?>> obserList = new ArrayList<Class<?>>();
/**AttachObserver(通过实例注册观察者)
*<b>Notice:</b>obcan'tbenull,oritwillthrowNullPointerException
**/
public<T> void registerObserver(Tob){
if(ob==null) throw new NullPointerException();
this.registerObserver(ob.getClass());
}
/**
*AttachObserver(通过Class注册观察者)
*@paramcls
*/
public void registerObserver(Class<?>cls){
if(cls==null) throw new NullPointerException();
synchronized(obserList){
if(!obserList.contains(cls)){
obserList.add(cls);
}
}
}
/**UnattachObserver(注销观察者)
*<b>Notice:</b>
*<b>ItreverseswithattachObserver()method</b>
**/
public<T>void unRegisterObserver(Tob){
if(ob==null) throw new NullPointerException();
this.unRegisterObserver(ob.getClass());
}
/**UnattachObserver(注销观察者,有时候在未获取到实例使用)
*<b>Notice:</b>
*<b>ItreverseswithattachObserver()method</b>
**/
public void unRegisterObserver(Class<?>cls){
if(cls==null) throw new NullPointerException();
synchronized(obserList){
Iterator<Class<?>>iterator=obserList.iterator();
while(iterator.hasNext()){
if(iterator.next().getName().equals(cls.getName())){
iterator.remove();
break;
}
}
}
}
/**detachallobservers*/
public void unRegisterAll(){
synchronized(obserList){
obserList.clear();
}
}
/**Ruturnthesizeofobservers*/
public int countObservers(){
synchronized(obserList){
returnobserList.size();
}
}
/**
*notify all observer(通知所有观察者,在子类中实现)
*@paramobjs
*/
public abstract void notifyObservers(Object... objs);
/**
*notify one certain observer(通知某一个确定的观察者)
*@paramcls
*@paramobjs
*/
public abstract void notifyObserver(Class<?> cls, Object... objs);
/**
*notifyonecertainobserver
*@paramcls
*@paramobjs
*/
public abstract<T> void notifyObserver(T t, Object... objs);
}
//目标被观察者
public class ConcreteObservable extends Observable{
private static ConcreteObservableinstance = null;
private ConcreteObservable(){};
public static synchronized ConcreteObservablegetInstance(){
if(instance == null){
instance=newConcreteObservable();
}
returninstance;
}
@Override
public <T> void notifyObserver(T t, Object... objs){
if(t == null) throw new NullPointerException();
this.notifyObserver(t.getClass(), objs);
}
@Override
public void notifyObservers(Object... objs){
for(Class<?>cls : obserList){
this.notifyObserver(cls, objs);
}
}
//通过java反射机制实现调用
@Override
public void notifyObserver(Class<?>cls, Object...objs){
if(cls == null) throw new NullPointerException();
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods){
if(method.getName().equals("update")){
try{
method.invoke(cls,objs);
break;
}catch(IllegalArgumentException e){
e.printStackTrace();
}catch(IllegalAccessException e){
e.printStackTrace();
}catch(InvocationTargetException e){
e.printStackTrace();
}
}
}
}
}
//使用(实现Observer接口)
public class Text extends Activity implements Observer{
publicvoidonCreate(...){
ConcreteObservable.getInstance().registerObserver(Text.class);
....
}
public void update(Object...objs){
//做操作,如更新数据,更新UI等
}
}
【设计模式】java设计模式总述及观察者模式的更多相关文章
- Unity设计模式+Java设计模式,讲解+案例+PPT,一次性学会设计模式,拥抱高薪!
一个程序员对设计模式的理解:“不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开一把锁的模式, ...
- 简单工厂设计模式--Java设计模式(一)
一 概念: 简单工厂模式就是通过一个工厂类根据参数动态创建对应的类. 二 案例 我们以汽车作为例子,在现实生活中汽车只是一个抽象的产品,其中有很多类型的汽车才是具体产品,如奔驰.宝马.保时捷等等(当然 ...
- Java数据结构总述
array list map set 链表..array 和list类似,增删慢,读取快,list长度可变,array长度固定, 链表增删快的list set 是一个没有重复数据的集合 map 是一个 ...
- Java设计模式学习资源汇总
本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...
- Java设计模式知识整理
1.Java设计模式 Java设计模式分为三种类型,分别是: ①.创建型设计模式:是对对象创建过程的各种问题和解决方案的总结 包括:静态工厂模式.抽象工厂模式.单 ...
- Java设计模式学习笔记(一) 设计模式概述
前言 大约在一年前学习过一段时间的设计模式,但是当时自己的学习方式比较低效,也没有深刻的去理解.运用所学的知识. 所以现在准备系统的再重新学习一遍,写一个关于设计模式的系列博客. 废话不多说,正文开始 ...
- 折腾Java设计模式之中介者模式
博文原址:折腾Java设计模式之中介者模式 中介者模式 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并 ...
- java设计模式——建造者模式
一. 定义与类型 定义:将一个复杂对象的构建与它的表示分离,使用同样的构建过程可以创建不同的表示 用户只需制定需要建造的类型就可以得到它们,建造过程以及细节不需要知道 类型:创建型 建造者模式与工厂模 ...
- Java 之设计模式(总述)
1. 面向对象设计原则 单一职责原则: 一个类只负责一个功能领域中的相应职责 开闭原则: 软件实体应对扩展开放,而对修改关闭; 里氏代换原则: 所有引用基类对象的地方能够透明地使用其子类的对象; 依赖 ...
随机推荐
- P2P技术详解(一):NAT详解——详细原理、P2P简介
1. IPv4协议和NAT的由来 今天,无数快乐的互联网用户在尽情享受Internet带来的乐趣.他们浏览新闻,搜索资料,下载软件,广交新朋,分享信息,甚至于足不出户获取一切日用所需.企业利用互联网发 ...
- scanf———while(scanf ("%lu",&num) = =1)什么意思
scanf的返回值由后面的参数决定 scanf("%d%d", &a, &b); 如果a和b都被成功读入,那么scanf的返回值就是2 如果只有a被成功读入,返回值 ...
- AleNet模型笔记
谁创造了AlexNet? AlexNet是有Hinton大神的弟子Alex Krizhevsky提出的深度卷积神经网络.它可视为LeNet的更深更宽的版本. AlexNet主要用到的技术 成功使用Re ...
- django.db.utils.ProgrammingError: 1146 的解决办法
在models中设置完数据库相关的东西后执行命令 python manage.py makemigrations 此处无错误 再次执行 python manage.py migrate 发生报错 错误 ...
- swiper display:none 后 在显示 滑动问题
一般这种问题 必须在本身元素 或者父元素 显示出来 然后调用swiper实例 或者只需加两行 observer:true, // 修改swiper自己或子元素时,自动初始化swiper obs ...
- 网页底部广告悬浮弹窗(css)
有的单页面需要添加广告等悬浮div. 部分代码: <div class="flex"> 内容.... </div> 主要css代码: .flex{posit ...
- 整理的Java List Set Map是否有序,元素是否允许重复
整理的Java List Set Map是否有序,元素是否允许重复的说明,如下图:
- 初识Spring Boot框架(二)之DIY一个Spring Boot的自动配置
在上篇博客初识Spring Boot框架中我们初步见识了SpringBoot的方便之处,很多小伙伴可能也会好奇这个Spring Boot是怎么实现自动配置的,那么今天我就带小伙伴我们自己来实现一个简单 ...
- jboss规则引擎KIE Drools 6.3.0 Final 教程(3)
在前2部教程中,介绍了如何在本地运行.drools文件以及使用stateless的方法访问远程repository上的规则. KIE Drools还提供了一种叫有状态-stateful的访问方式. 运 ...
- OBJ文件格式分析工具: objdump, nm,ar
首先简要阐述关于gcc.glibc和 binutils模块之间的关系 一.关于gcc.glibc和binutils模块之间的关系 1.gcc(gnu collect compiler)是一组编译工具的 ...