结构型模式清单:适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式。
其中,适配器模式、装饰模式、享元模式、代理模式适用场景较多,须重点掌握。
一、适配器模式
适配器模式分为类适配器模式、对象适配器模式、缺省适配器模式。
适配器模式思想原理很简单。举个简单的例子:笔记本电脑充电。笔记本电脑充电的过程涉及三个元件:笔记本、电源适配器、插座。大家可以思考为什么有电源适配器。
首先,插座并不知晓笔记本充电时的额定功率的,因此,需要一个电源适配器,来达到笔记本充电时的额定功率。电源适配器是智能的,一方是220V插座电流流入,另一方是笔记本额定电流输出至笔记本。因此,适配器担任了一个重要的中介人角色。
1、类适配器模式
首先来看一下流程图。
Interface是接口,接口中定义了两个方法:run1、run2。Adapter是适配器类,Adaptee是被适配的类。
现在提出一个需求:Adaptee类只需要run2这一方法。
因此,Adapter就要协助Adaptee屏蔽掉run1这一方法。
有人会纳闷为什么要叫做“屏蔽”。事实上,直接继承接口,必须实现所有的方法。你不需要run1方法,你就要想办法屏蔽。
如何屏蔽run1方法?
上代码:
class Adapter{
public void run1(){
System.out.println("run1");
}
}
class Adaptee extends Adapter implements C{
public void run2() {
System.out.println("B's running");
}
}
interface Interface{
void run1();
void run2();
}
首先在Adapter中定义run1方法。class Adaptee extends Adapter implements C这句很关键。Adapter实现Interface接口,Adaptee继承Adapter类,又因为Adapter已经实现了run1方法,留给Adaptee实现的方法就只有run2了。这样,就达到了我们想要的目的:Adaptee类实现run2方法,不实现run1方法。
2、对象适配器模式
我们先来回顾一下类适配器模式是怎样写的:
class Adaptee extends Adapter implements C
Adapter是以类的形式来适配的。
试想一下某些场景,如果摆在你面前是许多许多个适配器,你觉得用类适配器模式方便吗?
不方便。
对象适配器对比类适配器最大优势就是动态装载适配器。也就是说你想用哪个适配器都可以通过适配器的实例对象来使用。
上代码:
interface Interface{
public void run1();
public void run2();
}
class Adapter{
public void run1(){
System.out.println("run1方法");
}
}
class Adaptee implements Interface{
private Adapter adapter;
public Adaptee(Adapter adapter){
this.adapter = adapter;
}
public void run1() {
this.adapter.run1();
}
public void run2() {
System.out.println("Adaptee实现run2方法");
}
}
很显然,我们可以通过Adaptee的构造函数将Adapter的实例对象注入Adaptee中,利用Adapter的run1方法来适配Interface接口中的run1方法。
3、缺省适配器模式
Earpods不兼容Andriod系统,嗯,Earpods压根就没对Andriod机提供适配功能。
因此,市场上出现了很多iOS、Andriod通用的耳机,都能与之适配。
缺省适配器属于类适配器的一种。是类适配器的特殊形式。缺省适配器实现接口中的所有方法,每一个方法都是空的,嗯,like this…”public void balabla(){}“。因此,被适配的对象只需继承缺省适配器就能使用或重写自己想要的方法。
上代码!
class iPhone extends Earphone{
public void iOS(){
System.out.println("iPhone");
}
}
class Galaxy extends Earphone{
public void Andriod(){
System.out.println("Galaxy");
}
}
class Earphone implements Interface{
public void iOS() {
}
public void Andriod() {
}
}
interface Interface{
void iOS();
void Andriod();
}
Tips:Earphone(Adapter)、iPhone(Adaptee)、Galaxy(Adaptee)