适配器模式
需求方法M1。但已经存在一个方法M2能实现需求功能,引入子类来覆盖M1方法(M1方法中调用已有的M2方法)。这个新子类就是适配器
将已有的方法转换为需求的另一种方法(一般由于方法名差异;参数不同)
这一模式中的“接口”是广义接口,可代指一个/一组方法集合
优点:无需修改已有内容,开闭;增加了透明性,用户复用性;可扩展性非常好
1. 类适配器
如何不修改已有结构的前提下,让用户通过目标类的方法R1,调用到已有类的方法R2?
引入子类,继承目标类,在覆盖目标类方法的时候去调用继承已有类/适配者的方法R2(里氏替换,子盖父)
同时作为目标类,已有类的子类
(缺点:JAVA不能多重继承,因此target类是一个接口就可以,具体/抽象类不行。接口模块有标记)
2. 对象适配器
适配器和目标抽象类仍然是继承关系,但是适配器和已有类是关联关系
(优势:规避目标类为具体类/抽象类;已有类存在多个,受限多重继承)
适配器中调用多个已有类内部的方法,多个已有类作为适配器对象
适配器可以放入配置文件,用反射机制生成具体适配器对象(符合开闭原则)
(关联关系-----一个类的对象定义为另一个类成员变量
接口可以继承接口,而类只能实现接口。)
(抽象类也可以包含具体方法)
桥接模式bridge
(类的多继承关系/蜡笔重构为关联关系/毛笔)
将不同的变化原因/维度做成独立的集成结构,提高了可扩展性,符合开闭
将抽象部分与实现部分分离,使其独立变化
具备公共的方法,放入抽象维度--抽象类/扩充抽象类;
抽象关联取代了传统的多层继承
桥接,将一个右边的子类颜色注入左边,在左边子类调用左父类注入的颜色
类之间的静态继承关系转换为动态的对象组合关系
从两个维度各选一个子类,放到客户端。二者都可以独立扩展修改
桥接模式实现
聚合关系
缺陷:
关联关系在抽象层,难以理解;正确识别两个独立变化维度较困难
组合模式(Composite Pattern)
组合模式依据树形结构来组合对象,用来表示部分以及整体层次
组合模式包含如下角色:
Component:抽象构件
抽象构件可以是接口或者抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子结构的方法,如增加子构件、删除子构件、获取子构件等。
Leaf:叶子构件
叶子构件在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。
Composite:容器构件
容器构件在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供了一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。
Client:客户类
客户类是可以通过抽象构件接口访问和控制组合构件中的对象
组合模式的优点:
可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。
客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。
定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构。
更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。
组合模式的缺点:
使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联。
增加新构件时可能会产生一些问题,很难对容器中的构件类型进行限制。
组合模式的适用环境:
需要表示一个对象整体或部分层次,在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,可以一致地对待它们。
让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无须关心对象层次结构的细节。
对象的结构是动态的并且复杂程度不一样,但客户需要一致地处理它们。
透明的组合模式
在透明组合模式中,抽象构件Component中声明了所有用于管理成员对象的方法,包括add、remove、getChild等方法,这样做的好处是确保所有的构件类都有相同的接口。在客户端看来,叶子对象与容器对象所提供的方法是一致的,客户端可以相同的对待所有对象。
安全的组合模式
在安全组合模式中,在抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明这些用于管理成员对象的方法。这种做法是安全的,因为根本不想叶子对象提供这些管理成员对象的方法,对于叶子对象,客户端不可能调用到这些方法。
优点
代码复用性:组合模式促进了代码的重用,因为它通过将相似的操作应用于树中的所有节点,从而减少了重复的代码。这使得在系统中使用组合模式时,可以更好地利用已有的代码,并且可以避免在多个地方编写相似的逻辑
核心是能够灵活且安全地处理多层嵌套的结构。通过组合模式,你可以轻松地构建出多层次的树形结构,并且可以统一对待树中的各个节点,无论是叶子节点还是组合节点。
装饰模式DECORATOR
想要更加灵活的替代继承关系,引入这一面向对象设计
动态的设计
一致性的/透明的修改==对共同父类修改
装饰模式需要涉及到以下几个角色:
抽象组件(Component):定义一个系列对象应该有的功能,今后的扩展调用均基于该接口实现
具体组件(SpecificComponent):抽象组件的具体实现,装饰类将对该具体实现进行扩展
抽象装饰类(Decorator):装饰类将通过继承该类来进行功能扩展,并且在该类中包含具体组件实例
具体装饰类(DecorateComponent):实现抽象装饰类的具体装饰类,用于对抽象装饰类中的具体组件功能调用的扩展
透明装饰模式和半透明装饰模式
透明装饰模式
在透明装饰模式中要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型。对客户端而言,具体构件类和具体装饰类对象没有任何区别。(缺点,无法单独调用装饰类的独有功能)
//不应该将对象声明为具体构件类型或具体装饰者类型
Window window=new Window();
//应该声明为抽象构件类型,向上转型
Component window=new Window();
半透明装饰模式
用具体装饰类型来定义装饰后的对象,而具体构件类型仍然可以使用抽象构件类型来定义,可以单独调用装饰的独有方法。(缺点:无法多次进行装饰)
//具体构件类型仍然可以使用抽象构件类型来定义
Component window =new Window();
//具体装饰类型来定义装饰后的对象
BlackBorderDec blackBorder=new BlackBorderDec(window);
//可以单独调用
blackBorder.setBlackBorder();
外观模式(Facade Pattern)
外部与子系统的通信通过一个统一的外观对象进行,为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易使用。
代理模式-proxy pattern
间接访问,对某对象访问的限制。(限制访客,保护其安全性)
可以在不修改目标对象代码的基础上,增强额外的功能操作,即扩展目标对象的功能
(其中prerequest方法是类似创建链接,写系统日志等前期准备;postrequest方法为链接结束后的一系列方法)
-
- 虚拟代理,这种方式通常用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
-
- 远程代理:最经典的代理模式之一,远程代理负责与远程JVM通信,以实现本地调用者与远程被调用者之间的正常交互
-
- 保护代理,当对目标对象访问需要某种权限时,提供对目标对象的受控保护,拒绝服务权限不够的客户。
-
- 缓冲代理:本地缓存以前访问的对象,下次访问调用
-
- 智能指引代理:主要用于调用目标对象时,附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它(C++智能指针)