Java设计模式之结构型模式

简介: Java设计模式之结构型模式

微信截图_20220517191308.png


适配器模式【Adapter】


【学习难度:★★☆☆☆,使用频率:★★★★☆】


定义:适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。


(1)类的适配(拓展、修改目标类的方法)


微信截图_20220517191346.png


通过继承和接口实现:继承原始类的方法,接口来实现新的方法。


(2)对象的适配(拓展、修改目标对象的使用方法)



微信截图_20220517191414.png


持有原始类的对象引用和接口实现:原始对象的方法通过引用该对象调用来实现,接口实现新的方法。


(3)接口适配(解决接口定义方法过多,有些接口方法不需要实现的问题)



微信截图_20220517191445.png


定义一个抽象类来实现目标接口的方法(空方法),再继承这个抽象类,要实现哪个方法,就重写哪个方法。


三种适配的使用场景:


类的适配器模式:


当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。


对象的适配器模式:


当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。


接口的适配器模式:


当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。


注意:适配器模式不适合在详细设计阶段使用它,它是一种补偿模式,专用来在系统后期扩展、修改时所用。


装饰模式【Decorator】


【学习难度:★★★☆☆,使用频率:★★★☆☆】


定义:装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。


微信截图_20220517191522.png


ITarget类是被装饰的接口,Decorator类是一个装饰类,可以为Target类动态的添加一些功能。


从上面可知,装饰模式和对象的适配模式很像,都是为了拓展对象的方法。但是他们有显著的不同:


(1)持有对象不同:


装饰模式,装饰者持有的是被装饰类型的接口。


对象的适配模式,适配器持有的是具体需要适配的对象。


(2)拓展方式不同:


装饰模式,并不增加被装饰对象的方法数,只是增强被装饰对象的方法或者功能。


对象的适配模式,增加了适配对象的方法数。


(3)目的不同:


装饰模式,是在不改变接口的前提下,加入新的责任或功能方法,增强功能。


对象的适配模式,是增加接口来适配原先的方法【使用新接口代替原先的接口,本质上是接口替换】。


代理模式【Proxy】


学习难度:★★★☆☆,使用频率:★★★★☆】


定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。


(1)静态代理


微信截图_20220517191603.png


在图中,IProxy是抽象角色,Proxy是代理角色,NJProxy、BJProxy是真实角色。


静态代理和装饰模式很像,都可以对代理/装饰的对象的方法进行修改。但是他们有显著的不同:


(1)装饰模式,装饰者在构造的时候需要传入被装饰的接口。


代理模式,代理者在构造的时候并不需要传入代理的接口。


(2)装饰模式,主要的目的是增强被装饰者的方法或功能。


代理模式,主要的目的是对代理访问对象进行控制,被代理的对象方法和功能并没有增强。


【对代理访问对象进行控制的理解】


比如马云擅长卖货,那么他适合代理阿里巴巴的运转;马化腾擅长社交,那么他适合代理腾讯的运转。


如果是使用装饰模式的话,那么马云既可以运转阿里巴巴,也可以运转腾讯,那么就乱套了。。。


使用案例:网络请求代理


(2)动态代理



微信截图_20220517191644.png


和静态代理不同,动态代理不是实现具体的代理接口,而是要实现InvocationHandler接口,在接口里调用代理的接口实现动态代理。


当我们需要代理的接口数量过多,且不需要对方法进行具体的处理的话,就可以使用动态代理。


使用案例:网络请求代理,Retrofit等


外观模式【Facade】


【学习难度:★☆☆☆☆,使用频率:★★★★★】


定义:为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。


(解决相关联类与类之间的依赖关系,将他们的依赖关系放到一个外观类中,可降低系统的复杂度)


微信截图_20220517191724.png


一幅图解外观模式:


微信截图_20220517191750.png


在这里,电脑Computer充当外观角色,它的各部分组件就充当子系统角色,而,User就充当了客户的角色。


Facade模式有下面一些优点:


1)对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。


2)实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。


3)降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。


4)只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。

Facade模式的缺点:


1) 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。


2) 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。拓展性比较差

由于外观模式提供了一个访问子系统的统一入口,常见的和单例模式组合使用比较多。

我们平时将一个非常复杂的方法分成多个私有子方法,再由一个统一的公用方法提供给外部,使用的就是外观模式。

 

桥接模式【Bridge】


【学习难度:★★★☆☆,使用频率:★★★☆☆】


定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。


微信截图_20220517191833.png


桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。


桥接模式的本质是:分离抽象和实现。只有将两者分离,它们才能独立地变化,也只有两者可以相对独立地变化时,系统才会有更好的可扩展性和可维护性。桥接模式很好地遵循了开闭原则,也较好地体现了Favor Composition Over Inheritance(优先使用对象组合/聚合原则)。


组合模式【Composite】


【学习难度:★★★☆☆,使用频率:★★★★☆】


定义:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ”单个对象“ 与 "组合对象"的含义。


微信截图_20220517191910.png


图中Leaf叫做叶子对象(单个对象),Composite叫做容器对象(组合对象)。


组合模式又可分为透明模式和安全模式:


透明方式:在Component中声明所有来管理子对象的方法,其中包括Add,Remove等。这样实现Component接口的所有子类都具备了Add和Remove方法。这样做的好处是叶节点和枝节点对于外界没有区别,它们具备完全一致的接口。


安全方式:在Component中不去声明Add和Remove方法,那么子类的Leaf就不需要实现它,而是在Composit声明所有用来管理子类对象的方法。


适用场景


(1)当想表达对象的部分-整体的层次结构时


(2)希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象时。


举例说明:


Component就好比一家知名美容美发店,在它旗下有加盟店(Leaf),也有自己的总店和分店(Composite),但是对于顾客来说,如果拥有这家店的会员卡,按道理来说,我无论是在加盟店还是总店、分店,对于使用应该是没有任何差异的,这个时候就需要使用组合模式。


同样的,一家大的跨国公司也可以使用组合模式来表明其公司结构。其结构就类似二叉树结构。


使用案例:Android的View和ViewGroup


享元模式【Flyweight】


【学习难度:★★★★☆,使用频率:★☆☆☆☆】


定义:享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。


微信截图_20220517191958.png


使用场景:  


1、当我们发现某个类型的对象有大量的实例,且他们功能相似时。


2、我们发现通过使用享元模式后能够提高系统的性能和不会带来更多的复杂度时。


使用案例:数据库连接池、线程池、RxBus


项目源码


Github项目源码地址:github.com/xuexiangjys…, 觉得有帮助的话记得给个star!~~


相关文章
|
9月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
1079 157
|
9月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
918 2
|
11月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
设计模式 存储 缓存
【设计模式】【结构型模式】享元模式(Flyweight)
一、入门 什么是享元模式? 享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来减少内存使用,特别适用于存在大量相似对象的情况。 它的核心思想是将对象的内在状态(不变
399 16
|
9月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
2546 35
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
277 0
|
9月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
656 8
|
11月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
11月前
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
设计模式 Java 数据库连接
【设计模式】【结构型模式】代理模式(Proxy)
一、入门 什么是代理模式? 代理模式(Proxy Pattern)是一种结构型设计模式,允许你提供一个代理对象来控制对另一个对象的访问。 代理对象在客户端和目标对象之间起到中介作用,可以在不改变目标对
408 10

热门文章

最新文章