为什么用结构性模式?
结构性模式
关注点“怎样组合对象/类
?”所以我们关注下类的组合关系类结构型模式
关心类的组合,由多个类可以组合成一个更大的(继承)对象结构型模式
关心类与对象的组合,通过关联关系
在一个类中定义另一个类的实例对象(组合)- 根据“
合成复用原则
”,在系统中尽量使用关联关系来替代继承关系
,因此大部分结构型模式都是对象结构型模式
。
- 适配器模式(Adapter Pattern):两个不兼容接口之间适配的桥梁。
- 桥接模式(Bridge Pattern):相同功能抽象化与实现化解耦,抽象与实现可以独立升级。
- 过滤器模式(Filter、Criteria Pattern):使用不同的标准来过滤一组对象。
- 组合模式(Composite Pattern):相似对象进行组合,形成树形结构。
- 装饰器模式(Decorator Pattern):向一个现有的对象添加新的功能,同时又不改变其结构。
- 外观模式(Facade Pattern):向现有的系统添加一个接口,客户端访问此接口来隐藏系统的复杂性。
- 享元模式(Flyweight Pattern):尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
- 代理模式(Proxy Pattren):一个类代表另一个类的功能。
🍭结构性模式之适配器模式
🍎定义
-
将
一个接口
转换成客户希望的另一个接口
,适配器模式使接口不兼容的那些类可以一起工作,适配器模式分为类结构型模式(继承)和对象结构型模式(组合)两种,前者(继承)类之间的耦合度比后者高,且要求程序员了解现有组件库中相关组件的内部结构,所以应用相对较少些。 -
别名也可以是 Wrapper,包装器。
适配器模式(Adapter)包含以下主要角色。
- 目标(Target)接口:可以是抽象类或接口。客户希望直接用的接口。
- 适配者(Adaptee)类:隐藏的转换接口。
- 适配器(Adpter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口。
🍔代码实现
/**
* 系统原有接口 player:可以播放电影,且返回字幕
*
*/
public interface Player {
String play();
}
/**
* 电影播放器
* 阅读器
*/
public class MoviePlayer implements Player {
@Override
public String play() {
System.out.println("正在播放电影");
String content = "你好";
System.out.println(content); // 并且打印字幕
return content;
}
}
/**
* 系统原有接口 可以翻译文字内容
*/
public interface Translator {
String translate(String content);
}
public class Zh_JPTranslator implements Translator {
@Override
public String translate(String content) {
if ("你好".equals(content)) {
return "萨瓦迪卡";
} else {
return "....";
}
}
}
类结构型实现:
/**
* 继承的方式:类结构模型,适配转换到了翻译器的功能上
*/
public class JPMoviePlayerAdapter extends Zh_JPTranslator implements Player {
// 被适配对象
private Player target;
public JPMoviePlayerAdapter(Player target) {
this.target = target;
}
@Override
public String play() {
String play = target.play();
// 转换字幕
String translate = translate(play);
System.out.println("日文:" + translate);
return translate;
}
}
public class MainTest {
public static void main(String[] args) {
Player player = new JPMoviePlayerAdapter(new MoviePlayer());
player.play();
}
}
正在播放电影
你好
日文:萨瓦迪卡
对象结构型实现:
public class JPMovierPlayAdaptor implements Player {
// 组合的方式
private Translator translator = new Zh_JPTranslator();
private Player target;
public JPMovierPlayAdaptor(Player target ){
this.target = target;
}
@Override
public String play() {
String play = target.play();
// 转换字幕
String translate = translator.translate(play);
System.out.println("日文:" + translate);
return null;
}
}
public class MainTest {
public static void main(String[] args) {
JPMovierPlayAdaptor playAdaptor = new JPMovierPlayAdaptor(new MoviePlayer());
playAdaptor.play();
}
}
正在播放电影
你好
日文:萨瓦迪卡
适配器
1.系统原有两个已存在接口 player、translate 没有任何关系
需求:现在有提个小…日本有人。看电影字幕是中文的不习惯
2.我们在不改变原有系统的基础上实现这个功能就需要一个适配器
系统原来存在的所有接口都不动。扩展一个新的类,来连接两个之前不同的类。
🍕应用场景
- 什么场景用到?
- Tomcat如何将Request流转为标准Request
- Spring AOP中的AdvisorAdapter是什么
- Spring MVC 中经典的 HandlerAdapter 是什么
- SpringBoot 中 WebMvcConfigurerAdapter为什么存在又取消
- …