【设计模式】适配器模式:攻敌三分,自留七分,以超兽武装的例子来谈谈适配器模式

news2024/10/6 12:32:07

文章目录

  • 1 适配器模式
    • 1.1 定义
    • 1.2 结构
    • 1.3 类图
      • 1.3.1 类适配器模式
      • 1.3.2 对象适配器模式
  • 2 例子
    • 2.1 类适配器模式
      • 2.1.1 代码
      • 2.1.2 效果图
    • 2.2 对象适配器模式
      • 2.2.1 代码
      • 2.2.2 效果通
  • 3 优缺点及适用环境
    • 3.1 优点
    • 3.2 缺点
      • 3.3 适用环境

1 适配器模式

1.1 定义

将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能在一起工作的那些类能一起工作。

适配器模式分为类适配器模式对象适配器模式,前者类(类适配器)之间的耦合度比后者高,而且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对少一些

1.2 结构

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

个人认为:适配器的作用就是让用户使用A的功能而达到B功能的效果。

1.3 类图

1.3.1 类适配器模式

image-20221116215131395

1.3.2 对象适配器模式

为什么要有对象适配器模式,因为类适配器模式违反了合成/聚合复用原则,也就是优先考虑组合/聚合来实现复用,其次考虑继承(使用继承需要严格遵循里氏代换原则,滥用继承会增加系统构建和维护的难度以及系统的复杂度)

image-20221117084647710

2 例子

在这里插入图片描述

国产动画片《超兽武装》中的角色就很符合适配器模式。他们可以以普通模式进行战斗,也可以通过异能锁(适配器)来召唤超兽武装进行战斗。角色(如龙戬)想要发送技能–寒影决,通过异能锁,将其变成了威力更为强大的超兽形态寒影决。

普通形态的龙戬

也可以攻击和使用寒影决

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eGhfMKLJ-1668647118412)(https://gitee.com/you-tanzhi/pic/raw/master/src=http%253A%252F%252Fi0.hdslb.com%252Fbfs%252Farchive%252Fb29068526b2823e6da7d77eff7679394cdeb1c67.jpg&refer=http%253A%252F%252Fi0.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto)]

异能锁

借助异能锁,超兽武装,将自己的寒影决变成超兽武装的寒影决,威力更大

在这里插入图片描述

超兽武装

可以攻击、使用超兽状态下的寒影决

在这里插入图片描述

2.1 类适配器模式

2.1.1 代码

在此例子中,有四个重要的角色 龙戬(DargonJian)、普通形态(Common)、超兽武装形态(Mocha)、异能锁(PowerLock)。使用适配器的目的即为龙戬在使用普通形态的技能时底层调用的是超兽武装形态的技能方法。

至于为什么是类适配器模式而不是对象适配器模式,核心就在于在将普通形态接口转化成超兽武装形态的过程中,适配器类继承了超兽武装形态的实现类,而不是创建一个超兽武装形态类的对象。

Common.interface

/* 普通状态 */
public interface Common {
    /* 攻击 */
    void attack();
    /* 大招 */
    void bigMove(String msg);

}

CommonImpl.java

/* 普通形态类 */
public class CommonImpl implements Common {

    @Override
    public void attack() {
        System.out.println("稀里哗啦做了一套广播体操,对敌人造成了1点伤害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("放出了大招"+msg);
    }
}

Mocha.interface

/* 超兽武装 */
public interface Mocha {
    /* 攻击 */
    void attack();
    /* 大招 */
    void bigMove(String msg);
}

MochaImpl.java

/*
* 超兽武装
* */
public class MochaImpl implements Mocha {

    @Override
    public void attack() {
        System.out.println("超兽武装形态下对敌攻击,造成1W点伤害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("超兽武装形态下放出了大招"+msg);
    }
}

PowerLock.java

/*
* 异能锁:适配器
* */
public class PowerLock extends MochaImpl implements Common {

    @Override
    public void attack() {

        super.attack();
    }

    @Override
    public void bigMove(String msg) {
        super.bigMove(msg);
    }
}

DargonJian.java

public class DragonJian {
    /* 龙戬攻击 */
    public void attack(Common common)
    {
        if(common == null)
        {
            throw new NullPointerException("没有普通形态");
        }
        common.attack();
    }
    /* 寒影决 */
    public void bigMove(Common common,String msg)
    {
        if(common == null)
        {
            throw new NullPointerException("没有普通形态");
        }
        common.bigMove(msg);
    }
}

Client.java

public class Client {
    public static void main(String[] args) {
        /* 龙戬 */
        DragonJian dragonJian = new DragonJian();
        /* 普通攻击*/
        dragonJian.attack(new CommonImpl());
        dragonJian.bigMove(new CommonImpl(),"寒影决");
        System.out.println("=====借助异能锁,超兽武装=====");
        dragonJian.attack(new PowerLock());
        dragonJian.bigMove(new PowerLock(),"寒影决");
    }


}

2.1.2 效果图

image-20221116233604098

2.2 对象适配器模式

这里为了符合合成/聚合复用原则,将原有的继承改成了组合/聚合的形式

2.2.1 代码

Client.java

public class Client {
    public static void main(String[] args) {
        /* 龙戬 */
        DragonJian dragonJian = new DragonJian();
        /* 普通攻击*/
        dragonJian.attack(new CommonImpl());
        dragonJian.bigMove(new CommonImpl(),"寒影决");
        System.out.println("=====借助异能锁,超兽武装=====");
        PowerLock powerLock = new PowerLock(new MochaImpl());
        dragonJian.attack(powerLock);
        dragonJian.bigMove(powerLock,"寒影决");
    }


}

Common.java

/* 普通状态 */
public interface Common {
    /* 攻击 */
    void attack();
    /* 大招 */
    void bigMove(String msg);

}

CommonImpl.java

/* 普通形态类 */
public class CommonImpl implements Common {

    @Override
    public void attack() {
        System.out.println("稀里哗啦做了一套广播体操,对敌人造成了1点伤害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("放出了大招"+msg);
    }
}

DragonJian.java

public class DragonJian {
    /* 龙戬攻击 */
    public void attack(Common common)
    {
        if(common == null)
        {
            throw new NullPointerException("没有普通形态");
        }
        common.attack();
    }
    /* 寒影决 */
    public void bigMove(Common common, String msg)
    {
        if(common == null)
        {
            throw new NullPointerException("没有普通形态");
        }
        common.bigMove(msg);
    }
}

Mocha.java

/* 超兽武装 */
public interface Mocha {
    /* 攻击 */
    void attack();
    /* 大招 */
    void bigMove(String msg);
}

MochaImpl.java

/*
* 超兽武装
* */
public class MochaImpl implements Mocha {

    @Override
    public void attack() {
        System.out.println("超兽武装形态下对敌攻击,造成1W点伤害");
    }

    @Override
    public void bigMove(String msg) {
        System.out.println("超兽武装形态下放出了大招"+msg);
    }
}

PowerLock.java

/*
* 异能锁:适配器
* */
public class PowerLock implements Common {

    MochaImpl mocha = new MochaImpl();

    public PowerLock(MochaImpl mocha) {
        this.mocha = mocha;
    }

    @Override
    public void attack() {

        mocha.attack();
    }

    @Override
    public void bigMove(String msg) {
        mocha.bigMove(msg);
    }
}

2.2.2 效果通

image-20221116234513162

3 优缺点及适用环境

3.1 优点

  • 一个对象适配器可以把多个不同的适配器适配到同一个目标
  • 可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据"里氏代换原则",适配者的子类也可以通过该适配器进行适配。
  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无需修改原有的代码。增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。

3.2 缺点

  • 对于Java、C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。
  • 在Java、C#等语言中,类适配者模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。

3.3 适用环境

系统需要使用现有的类,而这些类的接口不符合系统的需要。想要建立一个可以重复使用的类,用于一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。
是关联关系,根据"里氏代换原则",适配者的子类也可以通过该适配器进行适配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/11723.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深入理解C++】RTTI、dynamic_cast、typeid()

文章目录1.RTTI2.dynamic_cast运算符3.typeid运算符4.RTTI与虚函数表1.RTTI RTTI(Run Time Type Identification),即运行时类型识别,通过 RTTI,程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。 RTTI 提供了两…

数据库命名规范

1、mysql 规范 1.1 表名规范 模块_功能点 示例:alllive_log alllive_category。采用26个英文字母(区分大小写)和0-9的自然数(经常不需要)加上下划线_组成,命名简洁明确,多个单词用下划线_分隔,一个项目一个数据库。全部小写命名&#xff0c…

嵌入式分享合集103

一、EEPROM和Flash 存储器分为两大类:RAM和ROM,本文主要讨论ROM。ROM最初不能编程,出厂什么内容就永远什么内容,不灵活。 后来出现了PROM,可以自己写入一次,要是写错了,只能换一片,自…

React中的生命周期函数

生命周期的三个阶段: 1.创建时(挂载阶段) ①执行时机:组件创建时(页面加载时) ②执行顺序:constructor()->render()->componentDidMount() import React, { Com…

nodejs+vue+elementui共享充电宝管理系统express

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 2 前端技术:nodejsvueelementui 前端:HTML5,CSS3、JavaScript、VUE 功能介绍 管理员:…

H5基本开发2——(HTML文档基本结构)

现实生活中,任何一个文档都是具有一定的格式,不同的文档,基本格式不同,例如:请假条、调休单、剧本、年中总结、十九大报告、等等,而我们所编写等html文档也是具有一定的编写基本格式的 事实上W3C组织一直致…

[附源码]java毕业设计教学辅助系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

TwoModalBERT进行角色分类

你是否遇到过数据集中有多个文本特性的情况?例如,根据消息的上下文正确地对消息进行分类,即理解前面的消息。比如说我们有下面的数据集,需要对其进行分类。 当只考虑message时,你可以看到它的情绪是积极的,因为“incr…

关于电影的HTML网页设计—— 电影小黄人6页 HTML+CSS+JavaScript

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置,有div的样式格局,这个实例比较全面,有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 精彩专栏推荐&#x1f4…

【Pytorch with fastai】第 10 章 :NLP 深入探讨 RNN

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

【JavaScript高级程序设计】重点-第五章笔记:Date、RegExp、原始值包装类、单例内置对象

文章目录基本引用类型1.Date1.1 继承的方法1.2 日期格式化方法1.3 日期/时间组件方法2.RegExp正则表达式2.1 RegExp 实例属性2.2 RegExp 实例方法2.3 RegExp 构造函数属性3.原始值包装类型3.1 Boolean3.2 Number3.3 String3.3.1 JavaScript 字符3.3.2 normalize()方法3.3.3 字符…

AI 实战篇 |十分钟学会【动物识别】,快去寻找身边的小动物试试看吧【送书】

🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏制作专栏推荐:游戏制作 &…

计算机毕业设计node.js+vue在线日程管理系统

项目介绍 我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,在线日程管理系统被用户普遍使用,为方便用户能够可以随时进行在线管理自己的日程的数据信息,特开发了基于在线日程管理…

【Pytorch with fastai】第 11 章 :使用 fastai 的中级 API 进行数据处理

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

第2关:子节点创建、列出、删除

子节点创建、列出 首先,需要启动服务器,并使用zkCli.sh连接服务器,进入客户端命令行界面(如第一关所述)。 创建子节点类似于创建新的节点,子节点也具有四种类型的节点。唯一的区别是:子节点的…

redis学习4-list

基本的数据类型,列表,redis命令是不区分大小写的 在redis中,我们可以把list玩成,线,队列,阻塞队列! 所有的list命令都是用l开头的 [rootcentos7964 bin]# redis-cli -p 6379 127.0.0.1:6379> LPUSH li…

Oracle Primavera Unifier计划管理器(Planning Manager)

目录 一、前言 二、介绍 一、前言 在计划管理器中,Oracle Primavera Unifier 用户可以计划新项目/外壳和提案,并为已在 Unifier 中运行的项目/外壳创建预测。他们不能像在 Unifier 中管理真实项目/外壳那样管理计划的项目/外壳;但是,他们可…

Observer

一些比较方便的 DOM 监测的 API。 一个 Observer 实例具备的实例方法: observe。向监听的目标集合添加一个元素。unobserve。停止对一个元素的观察。disconnect。终止对所有目标元素的观察。… 一、IntersectionObserver 提供了一种异步检测目标元素与祖先元素或…

图解LeetCode——792. 匹配子序列的单词数(难度:中等)

一、题目 给定字符串 s 和字符串数组 words, 返回 words[i] 中是s的子序列的单词个数 。 字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是none),而不改变其余字符的相对顺序。 例如, “ace” 是 “abcde” 的…

css3对页面打印设置的一些特殊属性,如@page,target-counter等

公司内部应业务需求,需要将html生成pdf并能打印,前后台都各有方式,这里综合比较选择用java去生成,避免了前端生成带来的诸多问题,后台用的框架是 iTextPdf 但是在做的同时发现用iText实现的pdf生成和公司的业务需要生成…