• 设计模式学习笔记(五:适配器模式)


    1.1概述

        在实际生活中有很多和适配器类似的问题,比如有A型螺母和B型螺母,那么用户可以在A型螺母上直接使用按着A型螺母标准生产的A型螺丝,同样用户可以在B型螺母上直接使用按着B型螺母标准生产的B型螺丝。但是由于A型螺母和B型螺母标准不同,所以用户在A型螺母上不能直接使用B型螺丝,反之亦然。那现在有什么办法可以解决这个问题呢?具体办法如下:

        生产一种“A型螺母适配器”,这种A型螺母适配器的前端符合A型螺母标准要求,可以直接拧在A型螺母上,后端焊接一个B型螺母。现在用于借助A型螺母适配器就可以在A型螺母上使用B型螺丝。

        适配器模式是将一个类的接口(被适配者)转换成客户希望的另外一个接口(目标)的成熟模式,该模式中涉及有目标、被适配者和适配器。适配器模式的关键是建立一个适配器,这个适配器实现了目标接口并包含有被适配者的引用。

     

    1.2模式的结构

         由于Java不支持多重继承,即一个类只能有一个父类,所以下面介绍的对象适配器的结构具体角色,共包含三种角色:

    (1)目标(Target):目标是一个接口,该接口是客户想使用的接口。

    (2)被适配者(Adaptee):被适配者是一个已存在的接口或者抽象类,这个接口或者抽象类需要适配。

    (3)适配器(Adapter):适配器是一个类,该类实现了目标接口并包含有被适配者的应用,即适配器的职责是对被适配者接口与目标接口进行适配。

        适配器模式结构的类图如下所示:

    1.3适配器模式的优点

    (1)目标和被适配者是完全解耦关系。

    (2)适配器模式满足“开-闭原则”。当添加一个实现Adaptee接口的新类时,不必修改Adapter,Adapter就能对这个新类的实例进行适配。

    1.4适合使适配器模式的情景

    (1)一个程序想使用已经存在的类,但该类所实现的接口和当前程序所使用的接口不一致。

    1.5适配器模式的使用

    以下通过一个简单的问题来描述适配器模式中所涉及的各个角色。

    现在用户已有一个两相的插座,但最近用户又有了一个新的三相插座。用户现有一台洗衣机和一台电视机,洗衣机按着三相插座的标准配有三相插头,而电视机按着两相插座的标准配有两相插头,现在用户想用新的三相插座来使用洗衣机和电视机,即用新的三相插座为洗衣机和电视机接通电流。

    针对上面问题,使用适配器模式设计若干个类,具体如下:

    首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图3所示:

    图3  具体编写类及接口与类图对应关系

    (1)目标(Target

    本问题中,目标(Target)接口的名字是ThreeElectricOutlet,用来刻画三相插座,该接口定义的方法是:connectElectricCurrent()。该接口代码如下:

    package com.liuzhen.five_adapter;
    
    public interface ThreeElectricOutlet {
        public abstract void connectElectricCurrent();
    }

    (2)被适配者(Adaptee

    对于本问题,被适配者是一个接口,该接口的名字是TwoElectricOutlet,刻画两相插座,该接口定义的方法是:connectElectricCurrent()。该接口代码如下:

    package com.liuzhen.five_adapter;
    
    public interface TwoElectricOutlet {
        public abstract void connectElectricCurrent();
    }

    (3)适配器(Adapter

    适配器的名字是ThreeElectricAdapter类,该;类实现了ThreeElectricOutlet接口并包含有TwoElectricOutlet接口变量。该类代码如下:

    package com.liuzhen.five_adapter;
    
    public class ThreeElectricAdapter implements ThreeElectricOutlet {
        TwoElectricOutlet outlet;          //定义一个二相插座的引用对象
        //构造函数
        ThreeElectricAdapter(TwoElectricOutlet outlet){
            this.outlet = outlet;
        }
        public void connectElectricCurrent() {
            // TODO Auto-generated method stub
            outlet.connectElectricCurrent();  //通过二相插座引用对象调用其具体方法,实现二相插座通电
        }
    
    }

    (4)洗衣机(Wash)类

         洗衣机配有三相插头,故该类要实现三相插座接口ThreeElectricOutlet,其代码如下:

    package com.liuzhen.five_adapter;
    
    public class Wash implements ThreeElectricOutlet {  //洗衣机使用三相插座
        String name;
        Wash(){
            name = "黄河洗衣机";
        }
        Wash(String name){
            this.name = name;
        }
    
        public void connectElectricCurrent() {
            // TODO Auto-generated method stub
            turnOn();
        }
        public void turnOn(){
            System.out.println(name+"开始洗衣服。");
        }
    
    }

     

    (5)电视机(TV)类

    电视机配有两相插头,故该类要实现两相插座接口TwoElectricOutlet,其代码如下:

    package com.liuzhen.five_adapter;
    
    public class TV implements TwoElectricOutlet {   //电视机使用两相插座
        String name;
        TV(){
            name = "长江电视机";
        }
        TV(String name){
            this.name = name;
        }
    
        public void connectElectricCurrent() {
            // TODO Auto-generated method stub
            turnOn();
        }
        public void turnOn(){
            System.out.println(name+"开始播放节目。");
        }
    
    }

     

    (6)具体使用

    通过FiveApplication类来具体实现上述相关类和接口,来实现适配器模式的运用,其代码如下:

    package com.liuzhen.five_adapter;
    
    public class FiveApplication {
        public static void main(String args[]){
            ThreeElectricOutlet outlet;      //目标接口(三相插座)
            Wash wash = new Wash();          //洗衣机
            outlet = wash;                   //洗衣机插在三相插座上
            System.out.println("使用三相插座接通电流:");
            outlet.connectElectricCurrent();  //接通电流,开始洗衣服
            TV tv = new TV();                //电视机
            ThreeElectricAdapter adapter = new ThreeElectricAdapter(tv);  //把电视机插在适配器上
            outlet = adapter;                //适配器插在三相插座上
            System.out.println("使用三相插座接通电流:"); 
            outlet.connectElectricCurrent();  //接通电流,开始播放电视节目
        }
    
    }

     

    运行结果如下:

    使用三相插座接通电流:
    黄河洗衣机开始洗衣服。
    使用三相插座接通电流:
    长江电视机开始播放节目。

     

    参考资料:

          1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5

  • 相关阅读:
    BZOJ3670:[NOI2014]动物园(KMP)
    415. [HAOI2009] 旅行
    U10223 Cx大帝远征埃及
    U10206 Cx的治疗
    2741. [济南集训 2017] 掰巧克力
    复习题目汇总 over
    7-20 表达式转换(25 分)
    7-19 求链式线性表的倒数第K项(20 分)(单链表定义与尾插法)
    7-18 银行业务队列简单模拟(25 分)
    7-17 汉诺塔的非递归实现(25 分)(有待改进)
  • 原文地址:https://www.cnblogs.com/liuzhen1995/p/5983800.html
Copyright © 2020-2023  润新知