【设计模式】之适配器模式

适配器模式

什么是适配器模式

  • 适配器模式属于结构型模式,可以使得两个不匹配的接口可以协同工作。
  • 适配器模式允许两个不匹配的类通过将其中一个接口类型转换成另一个客户端期望的接口类型,从而达到二者协同工作。
  • 适配器模式也叫包装器。
    适配器模式在 Gang of Four 书中原始的定义如下:

    将一个类的接口类型转换成另一个客户端期望的接口类型。
    适配器可以让多个类协同工作即使他们本来是不匹配的接口类型。

适配器模式的应用场景

  • 考虑一个这样的场景,你在印度购买了一个轻便的笔记本,最近你刚搬到英国。但是英国的电子插座和印度的不一样。因此,你的笔记本不能直接工作了。
    你必须去购买一个适配器,可以为你的印度笔记本可以在英国的插座上充电。
  • 当你有一个需要与新系统集成的遗留接口时,新系统不能直接接收遗留库的工作方式。由于遗留库不再进行开发了,所以我们需要使用适配器促使两种不同的类型进行工作。
  • 你使用 Mac 时,经常需要转接头才能连接到会议室的投影仪,这个转接头,就是适配器,使得原本 Mac 、投影仪互不相容的两个物件可以协同工作。

适配器模式的特点

  • 客户端通过使用目标接口调用适配器的方法向适配器发起请求。
  • 适配器通过适配器接口将请求转换成适配者的一个或多个调用。
  • 客户端收到调用结果,并且不感知存在一个适配器在做这个转换工作。

何时使用适配器模式

  • 如果你想要将已经存在的类和他们的接口类型去匹配你最后需要的接口类型,就可以使用适配器模式。
  • 如果你想创建可重用类以帮助在不匹配的两个类之间进行接口式交互。

适配器模式示例

劳埃德银行是一家提供全球性服务的国际性银行。境外账户持有人的税率为 0.03%。
在印度,它提供2种类型的账户,普通和白金。税法不适用于印度账户。
现在离岸账户就匹配不了印度账户了。
所以需要设计出一个账户适配器 AccountAdapter 促使2种不同的账户类型还可以继续一块工作。

这个示例的交互图如下所示。
在这里,客户端仅仅需要调用适配器的 getBalance() 方法。
适配器调用适配者的 getOffshoreBalance() 方法并返回客户端期望的结果。
适配器内部的 getBalance() 方法将会通过扣除税金来计算账户余额。

同时它持有适配者的一个实例。
这样使得客户端和适配者完全解耦。只有适配器知道它们两个(客户端、适配者)。

OffshoreAccount.java

package org.byron4j.cookbook.designpattern.adapter;

/**
 * 离岸账户
 */
public class OffshoreAccount {

    private double balance;

    /**税率*/
    private static final double TAX_RATE = 0.04;

    public OffshoreAccount(final double balance) {
        this.balance = balance;
    }

    public double getTaxRate() {
        return TAX_RATE;
    }

    public double getOffshoreBalance() {
        return balance;
    }

    public void debit(final double debit) {
        if (balance >= debit) {
            balance -= debit;
        }
    }

    public void credit(final double credit) {
        balance += balance;
    }
}

Account.java

package org.byron4j.cookbook.designpattern.adapter;

/**
 * 账户接口类型
 */
public interface Account {
    /**
     * 获取账户余额
     * @return
     */
    public double getBalance();

    /**
     * 是否可以透支
     * @return
     */
    public boolean isOverdraftAvailable();

    /**
     * 贷款; 贷款后账户余额增多
     * @param credit
     */
    public void credit(final double credit);
}

AbstractAccount.java

package org.byron4j.cookbook.designpattern.adapter;

public class AbstractAccount implements Account {
    /**
     * 账户余额
     */
    private double balance;
    /**
     * 是否可以透支
     */
    private boolean isOverdraftAvailable;

    public AbstractAccount(final double size) {
        this.balance = size;
    }

    @Override
    public double getBalance() {
        return balance;
    }

    @Override
    public boolean isOverdraftAvailable() {
        return isOverdraftAvailable;
    }

    public void setOverdraftAvailable(boolean isOverdraftAvailable) {
        this.isOverdraftAvailable = isOverdraftAvailable;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + " Balance=" + getBalance()
                + " Overdraft:" + isOverdraftAvailable();
    }

    @Override
    public void credit(final double credit) {
        balance += credit;
    }
}

PlatinumAccount.java

package org.byron4j.cookbook.designpattern.adapter;

/**
 * 白金帐户: 可以透支
 */
public class PlatinumAccount extends AbstractAccount {

    public PlatinumAccount(final double balance) {
        super(balance);
        // 可以透支
        setOverdraftAvailable(true);
    }
}

StandardAccount.java

package org.byron4j.cookbook.designpattern.adapter;

/**
 * 普通账户: 不能透支
 */
public class StandardAccount extends AbstractAccount {

    public StandardAccount(final double balance) {
        super(balance);
        // 不能透支
        setOverdraftAvailable(false);
    }
}

AccountAdapter.java

package org.byron4j.cookbook.designpattern.adapter;

/**
 * 账户适配器; 适配器继承于目标账户。
 * 适配器(转接头)的目标是将离岸账户(会议室中的Mac电脑)转为 AbstractAccount(可以连接投影仪)
 */
public class AccountAdapter extends AbstractAccount {

    /**需要被适应的账户--适配者*/
    private OffshoreAccount offshoreAccount;

    /**
     *
     * @param offshoreAccount  适配者--会议室中的 mac 电脑
     */
    public AccountAdapter(final OffshoreAccount offshoreAccount) {
        super(offshoreAccount.getOffshoreBalance());

        // 适配器持有适配者的引用
        this.offshoreAccount = offshoreAccount;
    }

    /**
     * 计算扣除税款后的离岸账户余额
     * @return
     */
    @Override
    public double getBalance() {
        // 离岸税率
        final double taxRate = offshoreAccount.getTaxRate();

        // 离岸账户余额
        final double grossBalance = offshoreAccount.getOffshoreBalance();

        // 需要扣除的税款
        final double taxableBalance = grossBalance * taxRate;

        // 扣除离岸税款后的账户余额
        final double balanceAfterTax = grossBalance - taxableBalance;

        return balanceAfterTax;
    }
}

AdapterTest.java


package org.byron4j.cookbook.designpattern;

import org.byron4j.cookbook.designpattern.adapter.AccountAdapter;
import org.byron4j.cookbook.designpattern.adapter.OffshoreAccount;
import org.byron4j.cookbook.designpattern.adapter.StandardAccount;
import org.junit.Test;

public class AdapterTest {
    @Test
    public void test(){
        StandardAccount sa = new StandardAccount(2000);
        System.out.println("Account Balance= " + sa.getBalance());

        //Calling getBalance() on Adapter
        AccountAdapter adapter = new AccountAdapter(new OffshoreAccount(2000));
        System.out.println("Account Balance= " + adapter.getBalance());
    }
}

原文地址:https://www.cnblogs.com/fefi521/p/9880226.html

时间: 2024-08-30 13:15:01

【设计模式】之适配器模式的相关文章

设计模式之适配器模式

适配器模式(Adapter Pattern)有时候也称包装样式或者包装.将一个类的接口转接成用户所期待的.一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类别自己的接口包裹在一个已存在的类中. Adapter Pattern有两种: 类的Adapter Pattern(继承) 对象的Adapter Pattern(委托) 下面我们用第一种来实现适配器模式: 我们首先来看看类图: 具体实现如下: Banner类: public class Banner { private Stri

设计模式之适配器模式(Adapter Pattern)

适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 1. 解决的问题 即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 2. 模式中的角色 2.1 目标接口(Target):客户所期待的接口.目标可以是具体的或抽象的类,也可以是接口. 2.2 需要适配的类(Adaptee):需要适配的类或适配者类. 2.3 适配器(Adapter):通过包装一个需要适配的对象,把

大话设计模式_适配器模式(Java代码)

适配器模式:将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 简单描述: 大话设计模式中的截图: 代码例子: AbstractPlayer类: 1 package com.longsheng.adapter; 2 3 public abstract class AbstractPlayer { 4 5 public abstract void attack(); 6 7 public abstract void defenc

螃蟹学PHP设计模式之适配器模式

之前对java的设计模式略有了解,但是螃蟹目前是靠PHP吃饭,所以对于进阶学习php设计模式还是很有必要.螃蟹虽然做开发两年了,但是在老鸟眼中还是菜鸟,为了自己写的代码更容易维护和进行团队协作,所以我要搞定设计模式.希望螃蟹今年能创业成功或找个好工作. 1.适配器模式 螃蟹的理解是你买了港行的iphone手机,发现自家的插座和手机自带的插头不配,怎么办呢,就需要一个转换器(适配器).可能原来系统的类不是你设计的,但是现在你要使用原来的类,发现有问题,但原来的类又不能动,或者不需要动,这样你写一个

Java设计模式之适配器模式(Adapter Pattern)

Adapter Pattern的作用是在不改变功能的前提下转换接口.Adapter分为两类,一类是Object Adapter, 另一类是Class Adapter.由于Class Adapter的实现需要用到多继承,而Java不支持多继承,所以这里只关注Object Adapter. 在JDK1.5之前是没有 java.util.Iterator 接口的,java.util.Enumeration 接口起着 Iterator 的作用.那么如果我们需要维护一些年代比较久远的代码,可能就会面临着没

Head First 设计模式之适配器模式与外观模式

Head First设计模式之适配器模式与外观模式 前言: 之前讲过装饰者模式,将对象包装起来并赋予新的职责,这一章我们也会将对象进行包装,只不过是让它们看起来不像自己而像是别的东西.这样就可以在设计中将类的接口转化为想要的接口,以实现同的接口,此外还将讲述另一个模式,将对象包装起来以简化接口. 1.   适配器简介 1.1 面向对象的适配器 真实世界的适配器比如位于美式插头和欧式插座之间的交流电适配器.面向对象的适配器是什么呢? 面向对象的适配器是将一个接口转化成另一个接口,以符合客户的期望.

每天一个设计模式-3 适配器模式(Adapteer)

每天一个设计模式-3 适配器模式(Adapteer) 1.现实中的情况 旧式电脑的硬盘是串口的,直接与硬盘连接,新硬盘是并口的,显然新硬盘不能直接连在电脑上,于是就有了转接线.好了,今天的学习主题出来了“适配器”. 2.联系编程 有一个电源类,一个旧的硬盘类,还有一个新硬盘类:电源类能直接适配旧硬盘类,但不能和新硬盘适配. 这时,可以添加一个适配器类,这里采用对象引用的方式实现适配器. 3.类图 模式简图: 测试时使用的类图: 4.代码 NewDiskApi: public interface

Java编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)

1.组合和继承之间的选择 组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承则是隐式的做. 组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形.即在新类中嵌入某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口.为取得此效果,需要在新类中嵌入一个现有类的private对象.但有时,允许类的用户直接访问新类中的组合成分是极具意义的,即将成员对象声明为public.如果成员对象自身都隐藏了具体实现,那么这种做法是安全的.当用户能够了

JAVA学习笔记--策略设计模式与适配器模式

一.策略设计模式 创建一个能够根据所传递对象的不同而具有不同行为的方法被称为策略设计模式:这类方法包含所要执行的算法中固定不变的部分,而"策略"包含变化的部分.策略就是传递进去的参数对象,它包含要执行的代码. 这种设计模式将算法分别独立封装起来,然后将其当做参数传递给方法从而让方法产生不同的行为,不同的算法可以进行替换(就像给方法不同的实参).我们可以知道,在策略设计模式中有三个部分:策略.策略引用.接收策略引用的方法(这是笔者自己根据理解给出的名词,并没有查询有没有这些术语).下面通

07.设计模式_适配器模式

转载自  http://www.cnblogs.com/zhili/p/AdapterPattern.html 一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将"将现存的对象"在新的环境中进行调用呢?解决这个问题的办法就是我们本文要介绍的适配器模式--使得新环境中不需要去重复实现已经存在了的实现而很好地把现有对象(指原来环境中的现有对象)加入到新环境来使用. 二.适配器模