设计模式-适配器模式

适配器模式

适配器模式(Adapter Pattern)把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

优点
  1. 客户端通过适配器可以透明地调用目标接口。
  2. 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
  3. 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
  4. 在很多业务场景中符合开闭原则。
缺点
  1. 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
  2. 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
适用场景

需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重新开发这些组件成本又很高。

模式结构

适配器模式(Adapter)包含以下主要角色。

  1. 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  2. 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  3. 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

示例 – 类适配器模式

现在有一个发动机,它有一个方法是work(),但是还需要能源。我们的系统中没有能源,但是另一个系统中有能源。此时,我们需要把两个东西结合起来,既能实现发动机的功能,还能利用能源。

发动机
package com.designpattern.adapter.classadapter.motor;

public interface Motor {
    void work();
}
能源
package com.designpattern.adapter.classadapter.energy;

public abstract class Energy {
    public abstract void burn();
}
汽油
package com.designpattern.adapter.classadapter.energy;

public class Petrol extends Energy{
    @Override
    public void burn() {
        System.out.println("Petrol is burning.");
    }
}
天然气
package com.designpattern.adapter.classadapter.energy;

public class Gas extends Energy {
    @Override
    public void burn() {
        System.out.println("Gas is burning.");
    }
}
适配器

现在要在发动机工作的时候同时使用能源,也就是通过一次调用实现两个方法。

天然气发动机
package com.designpattern.adapter.classadapter.adapter;

import com.designpattern.adapter.classadapter.energy.Gas;
import com.designpattern.adapter.classadapter.motor.Motor;

public class GasMotor extends Gas implements Motor {
    @Override
    public void work() {
        System.out.println("Motor is working.");
        super.burn();
    }
}
汽油发动机
package com.designpattern.adapter.classadapter.adapter;

import com.designpattern.adapter.classadapter.energy.Petrol;
import com.designpattern.adapter.classadapter.motor.Motor;

public class PetrolMotor extends Petrol implements Motor {
    @Override
    public void work() {
        System.out.println("Motor is working.");
        super.burn();
    }
}
测试
package com.designpattern.adapter.classadapter;

import com.designpattern.adapter.classadapter.adapter.GasMotor;
import com.designpattern.adapter.classadapter.adapter.PetrolMotor;
import com.designpattern.adapter.classadapter.motor.Motor;

public class Application {
    public static void main(String[] args) {
        Motor gasMotor = new GasMotor();
        gasMotor.work();
        Motor petrolMotor = new PetrolMotor();
        petrolMotor.work();
    }
}

输出:

Motor is working.
Gas is burning.
Motor is working.
Petrol is burning.

示例 – 对象适配器模式

现在对发动机提出了新的要求,我们找来了不同的材料来制造发动机,要求发动机在工作的时候告诉我们使用的是什么材料。这时候,适配器类是不能同时继承两个父类的,因此,需要改变使用方式。

材料
package com.designpattern.adapter.objectadapter.material;

public abstract class Material {
    public abstract void create();
}
package com.designpattern.adapter.objectadapter.material;

public class Icon extends Material {
    @Override
    public void create() {
        System.out.println("Use the icon to make the motor.");
    }
}
package com.designpattern.adapter.objectadapter.material;

public class Aluminum extends Material {
    @Override
    public void create() {
        System.out.println("Use the aluminum to make motor.");
    }
}
适配器

适配器类需要改造,要求同时在*work()中调用Material.create()Energy.burn()*两个方法,上面采取的继承父类方法已经不再适用,需要使用下面的方法。

package com.designpattern.adapter.objectadapter.adapter;

import com.designpattern.adapter.objectadapter.energy.Energy;
import com.designpattern.adapter.objectadapter.material.Material;
import com.designpattern.adapter.objectadapter.motor.Motor;

public class CarMotor implements Motor {
    private Energy energy;
    private Material material;

    public CarMotor(Energy energy, Material material) {
        this.energy = energy;
        this.material = material;
    }

    @Override
    public void work() {
        this.material.create();
        System.out.println("Motor is working.");
        this.energy.burn();
    }
}
测试
package com.designpattern.adapter.objectadapter;

import com.designpattern.adapter.objectadapter.adapter.CarMotor;
import com.designpattern.adapter.objectadapter.energy.Energy;
import com.designpattern.adapter.objectadapter.energy.Gas;
import com.designpattern.adapter.objectadapter.energy.Petrol;
import com.designpattern.adapter.objectadapter.material.Aluminum;
import com.designpattern.adapter.objectadapter.material.Icon;
import com.designpattern.adapter.objectadapter.material.Material;
import com.designpattern.adapter.objectadapter.motor.Motor;

public class Application {
    public static void main(String[] args) {
        //Material
        Material icon = new Icon();
        Material aluminum = new Aluminum();
        //Energy
        Energy petrol = new Petrol();
        Energy gas = new Gas();
        Motor car = new CarMotor(petrol, icon);
        car.work();
        car = new CarMotor(gas, icon);
        car.work();
        car = new CarMotor(petrol, aluminum);
        car.work();
        car = new CarMotor(gas, aluminum);
        car.work();
    }
}

输出

Use the icon to make the motor.
Motor is working.
Petrol is burning.
Use the icon to make the motor.
Motor is working.
Gas is burning.
Use the aluminum to make motor.
Motor is working.
Petrol is burning.
Use the aluminum to make motor.
Motor is working.
Gas is burning.

总结

类适配器模式,即在实现接口的同时继承类,这样可以在实现接口方法的时候调用父类的方法。

对象适配器模式,在实现接口的前提下,将被适配对象作为适配器类的属性添加进来,并在实现接口方法的时候调用被适配对象的方法。

因为JAVA的父类只能有一个,不支持多继承,因此,对象适配器模式的优势是很明显的。如果存在多个被适配对象,则可以一次性的全部作为适配器的属性添加进来(相当于多个父类)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值