结构型模式(Structural Pattern)用于将类或对象结合在一起形成更强大的结构,就像搭积木,可以通过简单的积木组合出复杂、功能强大的模型。
结构型模式 重要程度⭐⭐⭐⭐
⭐⭐⭐
⭐⭐⭐⭐
⭐⭐⭐
⭐⭐⭐⭐⭐
⭐
⭐⭐⭐⭐
一、适配器模式(Adapter)
生活中,充电插头有两脚的、三脚的,还有圆形的,如果想使这些插头都能工作,就需要一个多功能适配器
基本介绍适配器模式(Adapter Pattern)属于结构性模式,它可以将某个类的接口转换为客户端期望的另一个接口表示,主要目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作,其别名为包装器(Wrapper)。适配器模式主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。
工作原理让原本接口不兼容的类可以兼容
从用户的角度看不到被适配者,是解耦的
用户调用适配器转化出来的目标接口方法,适配器去再调用被适配者的相关接口方法
类适配器模式 实现原理Adapter 类继承 src 类,实现 dst 接口,完成 src 对 dst 的适配。
案例插座(Voltage220V)的输出电压是220V,充电插头(Voltage5V)输出电压是5V,这时候就需要一个适配器(VoltageAdapter)转换电压,才能给手机(Phone)充电
代码实现电源输出电压为220V
public class Voltage220V { public int output220V() { int src = 220; System.out.println("电源输出" + src + "V"); return src; } }充电器输出电压为5V
public interface Voltage5V { int output5V(); }适配器需要将220V转为5V
public class VoltageAdapter extends Voltage220V implements Voltage5V { @Override public int output5V() { int src = super.output220V(); int dst = src / 44; System.out.println("转换为" + dst + "V"); return dst; } }手机接收5V电压,判断电压是否为5V
public class Phone { public static void charging(Voltage5V voltage5V){ int v = voltage5V.output5V(); if(v == 5){ System.out.println("接收电压为5V,正常充电"); }else if(v > 5){ System.out.println("电压高于5V,无法充电"); } } }测试方法
@Test public void test01(){ System.out.println("====类适配器模式===="); Phone.charging(new VoltageAdapter()); }运行结果
====类适配器模式==== 电源输出220V 转换为5V 接收电压为5V,正常充电 分析由于 Java 是单继承机制,所以类适配器模式有一定的局限性
src 类的方法再 Adapter 中都会暴露出来,增加了使用的成本
由于继承了 src 类,所以它可以重写父类方法,使 Adapter 的灵活性增强了
对象适配器模式 实现原理基本的思路和类的适配器模式相同,只是将 Adapter 类做修改,使用聚合关系替代继承关系
代码实现沿用前面的代码,新建一个适配器,只是将原来的 Adapter 继承 src 类换为聚合的关系
public class VoltageAdapter2 implements Voltage5V { private Voltage220V voltage220V; public VoltageAdapter2(){ this.voltage220V = new Voltage220V(); } @Override public int output5V() { int src = this.voltage220V.output220V(); int dst = src / 44; return dst; } }测试方法
@Test public void test02(){ System.out.println("====对象适配器模式===="); Phone.charging(new VoltageAdapter2(new Voltage220V())); }运行结果
====对象适配器模式==== 电源输出220V 转换为5V 接收电压为5V,正常充电 接口适配器模式接口适配器模式也可称为缺省适配器模式,当不需要实现接口的全部方法时,可先设计一个抽象类实现接口,并为该接口的每个方法都提供一个默认实现,那么该抽象类的子类就可以有选择的覆盖父类的某些方法来实现需求。
适用于一个接口不想使用其所有的方法的情况
代码实现写一个接口,里面定义一些方法
public interface InterfaceMethod { void m1(); void m2(); void m3(); void m4(); }一个抽象类,实现该接口
public abstract class AbstractAdapter implements InterfaceMethod { @Override public void m1() { } @Override public void m2() { } @Override public void m3() { } @Override public void m4() { } }