常见的结构型模式:
- 适配器模式——把一个类的接口变成客户端所期待的另一种接口
- 装饰模式——又名包装模式,以对客户端透明的方式扩展对象的功能,是继承关系的替代方案
- 代理模式——开闭原则的直接支持
- 桥接模式
- 组合模式
- 外观模式
什么是结构型模式:
- 描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以将简单的积木组合成复杂的、功能强大的结构
一、适配器模式介绍
例如SpringMVC中常用适配器,跟接口有关系
1.1、适配器模式定义
当你想使用一个已经存在的类,而他的接口不符合你的需求,或者想创建一个可重用的类。可以用适配器模式,它与装饰模式都有“包装”的功能。
1.2、适配器分类
类适配器、对象适配、接口适配方式。
类适配器方式采用继承方式;对象适配方式使用构造函数传递
1.3、类适配器和对象适配器区别
- 类适配器:对象继承的方式,静态的定义
- 对象适配器:依赖于对象的组合,都是采用对象组合的方式
1.4、适配器的使用地方
(1)I/O库中适配器的使用:
OutputStreamWriter:是Writer的子类,将输出的字符流变为字节流,即:将一个字符流的输出对象变为字节流的输出对象。
InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即:将一个字节流的输入对象变为字符流的输入对象。
(2)Spring框架中适配器的使用
SpringAOP 里需要将每个 Advice(通知)都封装成对应的拦截器类型,返回给容器,所以需要使用适配器模式对Advice 进行转换
(3)第三方技术
在使用第三方的类库,或者说第三方的API的时候,我们通过适配器转换来满足现有系统的使用需求
(4)新旧系统集成
我们的旧系统与新系统进行集成的时候,我们发现旧系统的数据无法满足新系统的需求,那么这个时候,我们可能需要适配器,完成调用需求
(5)数据库同步
我们在使用不同数据库之间进行数据同步
1.5、适配器的优点缺点
优点:
- 让任何两个没有关联的类一起运行;
- 提高了类的复用;
- 增加了类的透明度,客户端只关注结果。
缺点:
- 过多使用会导致系统凌乱,追溯困难
二、代码示例
2.1、类适配器
示例1:日本电饭煲电源接口标准是110V电压,而中国标准电压接口是220V,所以要想在中国用日本电饭煲,需要一个电源转换器。
//定义日本和中国两种接口及其实现
//一、先定义日本220V电源接口和实现
//1.1、日本110V电源接口
public interface JP110VInterface {public void connect();
}
//1.2、日本110V电源接口实现
public class JP110VInterfaceImpl implements JP110VInterface {@Overridepublic void connect() {System.out.println("日本110V,接通电源,开始工作..");}
}//二、再定义中国220V电源接口和实现
public interface CN220VInterface {public void connect();
}
public class CN220VInterfaceImpl implements CN220VInterface {@Overridepublic void connect() {System.out.println("中国220V,接通电源,开始工作");}
}
//定义一个电压适配器
//三、要想在中国使用日本电饭煲,需要把电饭煲110v的电源接口适配成我们220V的电源接口,这就需要一个电源适配器
public class ElectricCooker {private JP110VInterface jp110VInterface;//日本电饭煲ElectricCooker(JP110VInterface jp110VInterface){this.jp110VInterface=jp110VInterface;}public void cook(){jp110VInterface.connect();System.out.println("开始做饭了..");}
}
public class PowerAdaptor implements JP110VInterface {private CN220VInterface cn220VInterface;//中国电饭煲public PowerAdaptor(CN220VInterface cn220VInterface) {this.cn220VInterface = cn220VInterface;}@Overridepublic void connect() {cn220VInterface.connect();}
}
//四、测试开始运行
public class AdaptorTest {public static void main(String[] args) {//220V电源接口CN220VInterface cn220VInterface = new CN220VInterfaceImpl();//适配器接口PowerAdaptor powerAdaptor = new PowerAdaptor(cn220VInterface);// 电饭煲ElectricCooker cooker = new ElectricCooker(powerAdaptor);cooker.cook();//使用了适配器,在220V的环境可以工作了。}
}
示例2:想用小米4数据线链接小米5手机,使用转换器。
//1.定义M4DataLine 代表USB ——————小米4数据线
class M4DataLine {public void connection() {System.out.println("使用小米4数据线连接...");}
}
//2.定义客户端使用的接口,与业务相关
interface Target {void connection();
}
class M5DataLine implements Target {@Overridepublic void connection() {System.out.println("使用小米5数据线连接...");}
}
//3.创建适配器类,继承了被适配类,同时实现标准接口——————转换器
class M5DataLineAdapter extends M4DataLine implements Target {@Overridepublic void connection() {System.out.println("插入 type-c 转接头");super.connection();}
}
//4.客户端代码,测试
public class AdapterMain {public static void main(String[] args) {Target target = new M5DataLine();target.connection();Target adapter = new M5DataLineAdapter();adapter.connection();}
}
//5.结果
使用小米5数据线连接...
插入 type-c 转接头
使用小米4数据线连接...
2.2、对象适配器
创建适配器类,实现标准接口,将这个调用委托给实现新接口的对象来处理
略....