结构型模式
– 分类:
• 适配器模式、代理模式、桥接模式、装饰模式、组合模式、外观模式、享元模式
– 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题。
 
结构型模式汇总
 
 
 
 
适配器的adapter模式
生活中的场景:
 
 
 
 
什么是适配器模式?
– 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
 
• 模式中的角色
– 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
– 需要适配的类(Adaptee):需要适配的类或适配者类。
– 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
 
 
 
 
 
 
 
 
类适配器:
class Adapter extends Adaptee implements Target{
public void request() {
super.specificRequest();
}
}
对象适配器
class Adapter implements Target{
private Adaptee adaptee;
public Adapter (Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
this.adaptee.specificRequest();
}
}
工作中的场景
– 经常用来做旧系统改造和升级
– 如果我们的系统开发之后再也不需要维护,那么很多模式都是没必要的,但是不幸的是,事实却是维护一个系统的代价往往是开发一个系统的数倍。
 
• 我们学习中见过的场景
– java.io.InputStreamReader(InputStream)
– java.io.OutputStreamWriter(OutputStream)
 
 
 
 
代理模式(Proxy pattern)
核心作用:
• 通过代理,控制对对象的访问!可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(即:AOP的微观实现!)
AOP(Aspect Oriented Programming面向切面编程)的核心实现机制!
 
 
 
– 核心角色:
• 抽象角色
– 定义代理角色和真实角色的公共对外方法
• 真实角色
– 实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
 
关注真正的业务逻辑!
• 代理角色
– 实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
 
将统一的流程控制放到代理角色中处理!
 
 
 
应用场景:
– 安全代理:屏蔽对真实角色的直接访问。
– 远程代理:通过代理类处理远程方法调用(RMI)
– 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。
 
• 比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时不可能将所有的图片都显示出来,这样就可以 使用代理模式,当需要查看图片时,用proxy来进行大图片的打开。
 
• 分类:
– 静态代理(静态定义代理类)
– 动态代理(动态生成代理类)
• JDK自带的动态代理
• javaassist字节码操作库实现
• CGLIB
• ASM(底层使用指令,可维护性较差)
 
 
 
静态代理(静态定义代理类)
 
 
 
 
 
动态代理(动态生成代理类)
• JDK自带的动态代理
• javaassist字节码操作库实现
• CGLIB
• ASM(底层使用指令,可维护性较差)
 
 
动态代理相比于静态代理的优点
– 抽象角色中(接口)声明的所以方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
 
 
JDK自带的动态代理
– java.lang.reflect.Proxy
• 作用:动态生成代理类和对象
– java.lang.reflect.InvocationHandler(处理器接口)
• 可以通过invoke方法实现对真实角色的代理访问。
• 每次通过Proxy生成代理类对象对象时都要指定对应的处理器对象
Star realStar = new RealStar();
StarHandler handler = new StarHandler(realStar);
Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class},handler); proxy.sing();
开发框架中应用场景:
– struts2中拦截器的实现
– 数据库连接池关闭处理
– Hibernate中延时加载的实现
– mybatis中实现拦截器插件
– AspectJ的实现
– spring中AOP的实现
• 日志拦截
• 声明式事务处理
– web service
– RMI远程方法调用
– ...
– 实际上,随便选择一个技术框架都会用到代理模式!!
 
 
 
AOP(Aspect-Oriented Programming,面向切面的编程)
– 它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。
 
 
 
常用术语:
– 切面(Aspect):其实就是共有功能的实现。
– 通知(Advice):是切面的具体实现。
– 连接点(Joinpoint):就是程序在运行过程中能够插入切面的地点。
– 切入点(Pointcut):用于定义通知应该切入到哪些连接点上。
– 目标对象(Target):就是那些即将切入切面的对象,也就是那些被通知的对象
– 代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。
– 织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。
 
 
 
开源的AOP框架
– AspectJ
 
 
桥接模式:
场景分析
– 商城系统中常见的商品分类,以电脑为类,如何良好的处理商品分类销售的问题?
– 这个场景中有两个变化的维度:电脑类型、电脑品牌。
 
 
桥接模式核心要点:
– 处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联。
 
 
 
 
 
 
桥接模式总结
– 桥接模式可以取代多层继承的方案。 多层继承违背了单一职责原则,复用性较差,类的个数也非常多。桥接模式可以极大的减少子类的个数,从而降低管理和维护的成本。
– 桥接模式极大的提高了系统可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有的系统,符合开闭原则。
 
 
 
桥接模式实际开发中应用场景
– JDBC驱动程序
– AWT中的Peer架构
– 银行日志管理:
• 格式分类:操作日志、交易日志、异常日志
• 距离分类:本地记录日志、异地记录日志
– 人力资源系统中的奖金计算模块:
• 奖金分类:个人奖金、团体奖金、激励奖金。
• 部门分类:人事部门、销售部门、研发部门。
– OA系统中的消息处理:
• 业务类型:普通消息、加急消息、特急消息
• 发送消息方式:系统内消息、手机短信、邮件
 
 
 
组合模式
使用组合模式的场景:
– 把部分和整体的关系用树形结构来表示,从而使客户端可以使用统一的方式处理部分对象和整体对象。
• 组合模式核心:
– 抽象构件(Component)角色: 定义了叶子和容器构件的共同点
– 叶子(Leaf)构件角色:无子节点
– 容器(Composite)构件角色: 有容器特征,可以包含子节点
 
 
 
 
 
组合模式工作流程分析:
– 组合模式为处理树形结构提供了完美的解决方案,描述了如何将容器和叶子进行递归组合,使得用户在使用时可以一致性的对待容器和叶子。
– 当容器对象的指定方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员,并调用执行。其中,使用了递归调用的机制对整个结构进行处理。
 
使用组合模式,模拟杀毒软件架构设计
 
 
 
开发中的应用场景:
– 操作系统的资源管理器
– GUI中的容器层次图
– XML文件解析
– OA系统中,组织结构的处理
– Junit单元测试框架
• 底层设计就是典型的组合模式,TestCase(叶子)、TestUnite(容器),Test接口(抽象)
 
 
Junit单元测试框架底层设计
– 底层设计就是典型的组合模式,TestCase(叶子)、TestUnite(容器)、Test接口(抽象)
 
 
 
 
装饰模式:
 
 
 
实现细节:
– Component抽象构件角色:
• 真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。
– ConcreteComponent 具体构件角色(真实对象):
• io流中的FileInputStream、FileOutputStream
– Decorator装饰角色:
• 持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象
。这样,就能在真实对象调用前后增加新的功能。
– ConcreteDecorator具体装饰角色:
• 负责给构件对象增加新的责任。
 
 
开发中使用的场景:
– IO中输入流和输出流的设计
– Swing包中图形界面构件功能
– Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper 类,增强了request对象的功能。
– Struts2中,request,response,session对象的处理
 
 
IO流实现细节:
– Component抽象构件角色:
• io流中的InputStream、OutputStream、Reader、Writer
– ConcreteComponent 具体构件角色:
• io流中的FileInputStream、FileOutputStream
– Decorator装饰角色:
• 持有一个抽象构件的引用:io流中的FilterInputStream、FilterOutputStream
– ConcreteDecorator具体装饰角色:
• 负责给构件对象增加新的责任。Io流中的BufferedOutputStream、BufferedInputStream等。
 
 
 
 
总结:
– 装饰模式(Decorator)也叫包装器模式(Wrapper)
– 装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新 的具体构建类和具体装饰类。
• 优点
– 扩展对象功能,比继承灵活,不会导致类个数急剧增加
– 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
– 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
• 缺点
– 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
– 装饰模式易于出错,调试排查比较麻烦。
 
 
装饰模式和桥接模式的区别:
– 两个模式都是为了解决过多子类对象问题。但他们の诱因不一样。桥
模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。装
饰模式是为了增加新的功能。
 
 
 
外观模式
迪米特法则(最少知识原则):
– 一个软件实体应当尽可能少的与其他实体发生相互作用。
 
 
 
 
外观模式核心:
– 为子系统提供统一的入口。封装子系统的复杂性,便于客户端调用。
 
 
 
基本案例
– 注册公司流程(不使用外观模式)
 
 
 
 
 
基本案例
– 注册公司流程(使用外观模式)
 
 
 
 
开发中常见的场景
– 频率很高。哪里都会遇到。各种技术和框架中,都有外观模式的使用。如:
• JDBC封装后的,commons提供的DBUtils类,Hibernate提供的工具类、Spring JDBC工具类等
 
 
 
享元模式
 
• 场景:
– 内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的对象,我们可以通过享元模式,节省内存。
• 核心:
– 享元模式以共享的方式高效地支持大量细粒度对象的重用。
– 享元对象能做到共享的关键是区分了内部状态和外部状态。
• 内部状态:可以共享,不会随环境变化而改变
• 外部状态:不可以共享,会随环境变化而改变
 
享元模式实现:
– FlyweightFactory享元工厂类
• 创建并管理享元对象,享元池一般设计成键值对
– FlyWeight抽象享元类
• 通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态。
– ConcreteFlyWeight具体享元类
• 为内部状态提供成员变量进行存储
– UnsharedConcreteFlyWeight非共享享元类
• 不能被共享的子类可以设计为非共享享元类
 
享元模式实现的UML图:
享元模式开发中应用的场景:
– 享元模式由于其共享的特性,可以在任何“池”中操作,
比如:线程池、数据库连接池。
– String类的设计也是享元模
优点
– 极大减少内存中对象的数量
– 相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
– 外部状态相对独立,不影响内部状态
 缺点
– 模式较复杂,使程序逻辑复杂化
– 为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态
使运行时间变长。用时间换取了空间。

设计模式GOF23(结构型模式:代理模式,适配模式,桥接模式,组合模式,装饰模式,外观模式,享元模式)的更多相关文章

  1. 【设计模式】结构型01代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) 定义:顾名思义,增加中间层,为其他对象提供一种代理以控制对这个对象的访问.核心在于代理二字. 1.和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理 ...

  2. GoF的23种设计模式之结构型模式的特点和分类

    结构型模式描述如何将类或对象按某种布局组成更大的结构.它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象. 由于组合关系或聚合关系比继承关系耦合度低,满足 ...

  3. 设计模式21---设计模式之享元模式(Flyweight)(结构型)

    1.讲解享元模式(结构型) 1.1享元模式定义 运用共享技术有效地支持大量细粒度对象. 享元:把内部状态共享出来 1.2享元模式要点 重点在于分离变与不变. 把一个对象的状态分为内部状态和外部状态,内 ...

  4. 设计模式(十二): Flyweight享元模式 -- 结构型模式

    说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...

  5. 设计模式(十)享元模式Flyweight(结构型)

    设计模式(十)享元模式Flyweight(结构型) 说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释 ...

  6. C#设计模式之十二享元模式(Flyweight)【结构型】

    一.引言   今天我们要讲[结构型]设计模式的第六个模式,该模式是[享元模式],英文名称是:Flyweight Pattern.还是老套路,先从名字上来看看."享元"是不是可以这样 ...

  7. 享元模式 FlyWeight 结构型 设计模式(十五)

    享元模式(FlyWeight)  “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...

  8. C#设计模式之十一享元模式(Flyweight Pattern)【结构型】

    一.引言 今天我们要讲[结构型]设计模式的第六个模式,该模式是[享元模式],英文名称是:Flyweight Pattern.还是老套路,先从名字上来看看.“享元”是不是可以这样理解,共享“单元”,单元 ...

  9. 设计模式11: Flyweight 享元模式(结构型模式)

    Flyweight 享元模式(结构型模式) 面向对象的代价 面向对象很好的解决了系统抽象性的问题,同时在大多数情况下也不会损及系统的性能.但是,在某些特殊应用中,由于对象的数量太大,采用面向对象会给系 ...

  10. 结构型---享元模式(Flyweight Pattern)

    引言 在软件开发过程,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非常严 ...

随机推荐

  1. SpringMVC错误:Failed to read candidate component class:file... ...

    Failed to read candidate component class:file错误分析和处理 org.springframework.beans.factory.BeanDefinitio ...

  2. .NET Core前后端分离快速开发框架(Core.3.0+AntdVue)

    .NET Core前后端分离快速开发框架(Core.3.0+AntdVue) 目录 引言 简介 环境搭建 开发环境要求 基础数据库构建 数据库设计规范 运行 使用教程 全局配置 快速开发 管理员登录 ...

  3. 一分钟带你了解下Spring Security!

    一.什么是Spring Security? Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架,它是用于保护基于Spring的应用程序的实际标准. Spring Secu ...

  4. postgresql , etcd , patroni 做failover

    os: centos 7.4etcd:3.2 主从IP信息192.168.56.101 node1 master192.168.56.102 node2 slave192.168.56.103 nod ...

  5. mysql5.7下载与安装

    一.完全卸载旧版mysql 参考文章:https://blog.csdn.net/hui1setouxiang/article/details/89816176 二.win10中下载安装mysql5. ...

  6. 【接口测试】HttpClient+fastJson 总结与案例

    多次理解,反复练习,破釜沉舟. HttpCLient是什么 Apache Jakarta Common 下的子项目 支持 HTTP 协议的客户端编程工具包 支持 HTTP 协议最新的版本 怎么利用Ht ...

  7. 如何使用Sping Data JPA更新局部字段

    问题描述 在更新数据时,有时候我们只需要更新一部分字段,其他字段保持不变.Spring Data JPA并未提供现成的接口,直接使用save()更新会导致其他字段被Null覆盖掉. 解决办法 通常有两 ...

  8. GitHub远程库的搭建以及使用

    GitHub远程库的搭建 一).配置SSH 步骤: 1).注册GitHub账号 2).本地git仓库与远程的GitHub仓库的传输要通过SSH进行加密 3).创建SSH key ​ 1.检查在用户主目 ...

  9. 【01】主函数main

    java和C#非常相似,它们大部分的语法是一样的,但尽管如此,也有一些地方是不同的. 为了更好地学习java或C#,有必要分清它们两者到底在哪里不同. 首先,我们将探讨主函数main. java的主函 ...

  10. MySQL数据每日备份

    1.window下通过命令方式 @echo offset "Ymd=%date:~,4%-%date:~5,2%-%date:~8,2%%time:~0,2%%time:~3,2%" ...