• 适配器模式


    适配器模式分为两种:类适配器模式和对象适配器模式。

    类适配器模式需要用到多重继承机制(C++支持)。

    然而Java/C#等语言不支持多重继承,那么可以采用对象适配器模式。

    本文首先讲解类适配器模式在C++中的实现,然后讲解对象适配器模式在Java中的实现。

    背景

    我们有一个绘图应用,可以在屏幕上绘制一些形状。该应用首先会获得该形状占据的区域大小,然后将形状绘制在此区域内。

    clip_image001

    客户端代码:

    int main(int argc, char** argv)
    {
        Shape* shape = new Shape();
    
        //获取该形状占据的矩形区域,以便于确定在哪个区域绘制该形状
        Rect* boundingBox = shape->BoundingBox();
    
        //绘制该形状
        /****/
    
        return 0;
    }

    现在我们引用了一个第三方库,里面有TextView类。

    clip_image001[4]

    我们希望可以把TextView绘制在屏幕上,可是TextView类没有BoundingBox方法,因此我们不知道TextView占据的区域形状也就无法直接绘制该类。解决方案如下:

    • 修改TextView类的代码,以增加BoundingBox方法。(不可行,我们可能无法获得源码)
    • 用适配器模式。(对,下面我们来详细讲解)

    适配器模式

    适配器模式就像手机适配器(手机充电器)可以把220V的交流电转换为手机可以直接使用的5V直流电。我们先介绍下适配器模式中的几个术语:

    • 目标类(Target):5V直流电
    • 适配者(Adaptee): 220V交流电
    • 适配器(Adapter):手机充电器

    我们知道客户端已经可以在屏幕上绘制Shape对象。然而不知道如何绘制TextView对象,因为它没有BoundingBox方法。我们考虑新建一个TextShape类,其含有BoundingBox方法。

    Shape是目标类(Target)。

    TextView是适配者(Adaptee)。

    TextShape是适配器(Adapter)。

    clip_image001[6]

    (图为类适配器模式)

    image

    (图为对象适配器模式)

    C++实现代码(类适配器模式)

    可以想象,适配器模式的关键是Adapter如何将Adaptee转换为Targe。如何转换取决于具体的应用。

    Adapter代码:

    Rect* TextShape::BoundingBox() const
    {
        //一个中文字符占用2个相对宽度
        //一个英文字符占用1个相对宽度
        //这里为了简单起见,一律认为是1个相对宽度
        float width = this->GetText().length();
        float heigh = 1.0;
        //高度和宽度都要乘上字体大小比例
        return new Rect(
                new Point(0, 0), 
                new Point(width * this->GetFontSize(), heigh * this->GetFontSize())
            );
    }

    客户端代码:

    //采用类适配器模式的话,客户端代码会比较容易
    //如果采用对象适配器模式,客户端的代码会多一点
    int main()
    {
        Shape* shape = new TextShape();
        Rect* boundingBox = shape->BoundingBox();
    
        return 0;
    }

    Java实现代码(对象适配器模式)

    适配器代码:

    //由于不支持多继承
    //需要在构造函数传入adaptee对象
    public class TextShape extends Shape{
        private TextView textView;
        public TextShape(TextView textView) {
            this.textView = textView;
        }
        
        @Override
        public Rectangle boundingBox() {
            //根据textView的内容计算占据的区域大小
            //这里需要较复杂的代码
            return null;
        }
    }

    客户端代码:

    public class Client {
        public static void main(String[] args) {
            TextView textView = new TextView();
            Shape shape = new TextShape(textView);
            
            shape.boundingBox();
        }
    }
  • 相关阅读:
    php学习----文件系统
    zabbix添加mysql自定义监控项
    mysql主从库不同步问题
    zabbix分区
    CentOs7.3 安装 MySQL 5.7.21 二进制版本及主从配置
    MySQL数据备份之mysqldump使用
    mysql 占用大量写I/O
    zabbix添加企业微信发送
    Centos7 更新软件及删除多余内核
    zabbix监控vCenter报错
  • 原文地址:https://www.cnblogs.com/dongchen/p/5111132.html
Copyright © 2020-2023  润新知