设计模式之禅之设计模式-适配器模式

简介: 一:适配器模式的定义        --->一个补救模式,这种模式可以让你从因业务扩展而系统无法迅速适应的苦恼中解脱而出。        --->贫血对象和充血对象,这两个名词很简单,在领域模型中分别叫做贫血领域模型和充血领域模型,有什么区别呢?一个对象如果不存储实体状态以及对象之间的关系,该对象就叫做贫血对象,对应的领域模型就是贫血领域模型,有实体状态和对象关系的模型就是充血领域模型        --->将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

一:适配器模式的定义
        --->一个补救模式,这种模式可以让你从因业务扩展而系统无法迅速适应的苦恼中解脱而出。
        --->贫血对象和充血对象,这两个名词很简单,在领域模型中分别叫做贫血领域模型和充血领域模型,有什么区别呢?一个对象如果不存储实体状
态以及对象之间的关系,该对象就叫做贫血对象,对应的领域模型就是贫血领域模型,有实体状态和对象关系的模型就是充血领域模型
        --->将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
        --->适配器模式又叫做变压器模式,也叫做包装模式(Wrapper),但是包装模式可不止一个,还包括了第17章讲解的装饰模式


二:适配器模式的角色

● Target目标角色(行为的发起方的接口)
        该角色定义把其他类转换为何种接口,也就是我们的期望接口。
● Adaptee源角色(行为的发起方不兼容的实现类)
        你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象,经过适配器角色的包装,它会成为一个崭新、靓丽的角色。
● Adapter适配器角色(行为发起方的代理角色。通过它,与不兼容方的实现进行转换,得到原有接口想要的数据)
        适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转换为目标角色,怎么转换?通过继承或是类关联的方式。


●如上图,B想用A的数据。但由于不兼容。B用C做适配器和A沟通,C内部转化形成B能识别的数据。

三:适配器模式的应用
适配器模式的优点
● 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成。
● 增加了类的透明性
        想想看,我们访问的Target目标角色,但是具体的实现都委托给了源角色,而这些对高层次模块是透明的,也是它不需要关心的。
● 提高了类的复用度
        当然了,源角色在原有的系统中还是可以正常使用,而在目标角色中也可以充当新的演员。
● 灵活性非常好
        某一天,突然不想要适配器,没问题,删除掉这个适配器就可以了,其他的代码都不用修改,基本上就类似一个灵活的构件,想用就用,不想就卸载。

四:适配器模式的应用场景
        适配器应用的场景只要记住一点就足够了:你有动机修改一个已经投产中的接口时,适配器模式可能是最适合你的模式。比如系统扩展了,需要使用一个已有或新建立的类,但这个类又不符合系统的接口,怎么办?使用适配器模式,这也是我们例子中提到的。


五:适配器模式的注意事项

        适配器模式最好在详细设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,没有一个系统分析师会在做详细设计的时候考虑使用适配器模式,这个模式使用的主要场景是扩展应用中,就像我们上面的那个例子一样,系统扩展了,不符合原有设计的时候才考虑通过适配器模式减少代码修改带来的风险。再次提醒一点,项目一定要遵守依赖倒置原则和里氏替换原则,否则即使在适合使用适配器的场合下,也会带来非常大的改造。

六:适配器模式的例子
【1】目标角色的接口(行为的发起方,试图兼容别的接口)

 1 package com.yeepay.sxf.template14;
 2 /**
 3  * 目标角色
 4  * 行为的发起方
 5  * @author sxf
 6  *
 7  */
 8 public interface IUserInfo {
 9     //获取名字
10     public String getNameById(Integer id);
11     //根据名字获取地址
12     public String  getAddressBydName(String name);
13 }
View Code

【2】目标角色原来的实现类

 1 package com.yeepay.sxf.template14;
 2 /**
 3  * 目标角色现有的实现类
 4  * 原有的规律
 5  * @author sxf
 6  *
 7  */
 8 public class UserInfo implements IUserInfo{
 9 
10     @Override
11     public String getNameById(Integer id) {
12         System.out.println("UserInfo.getNameById(与数据库交互返回名字sxf)");
13         return "sxf";
14     }
15 
16     @Override
17     public String getAddressBydName(String name) {
18         System.out.println("UserInfo.getAddressByName(与数据库交互返回名字sxd)");
19         return "smx";
20     }
21 
22     
23 }
View Code

【3】源角色,(想被目标兼容的接口)

 1 package com.yeepay.sxf.template14;
 2 
 3 import java.util.Map;
 4 
 5 /**
 6  * 源角色的接口
 7  * 不兼容的接口
 8  * @author sxf
 9  *
10  */
11 public interface OutUserInfo {
12     //根据id获取用户名
13     public Map<String, String> getNameById(String id);
14     //根据用户名获取地址
15     public Map<String, String> getAddressByName(String name);
16 }
View Code

【4】源角色实现类,(想被目标兼容的接口的实现类)

 1 package com.yeepay.sxf.template14;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 /**
 7  * 源角色
 8  * @author sxf
 9  *
10  */
11 public class OutUserInfoimpl implements OutUserInfo{
12 
13     @Override
14     public Map<String, String> getNameById(String id) {
15         Map<String, String> map=new HashMap<String, String>();
16         map.put("12345", "sxf");
17         map.put("1236", "hdd");
18         return map;
19     }
20 
21     @Override
22     public Map<String, String> getAddressByName(String name) {
23         Map<String, String> map=new HashMap<String, String>();
24         map.put("sxf", "smx");
25         map.put("hdd", "hnzz");
26         return map;
27     }
28 
29     
30 }
View Code

【5】适配器

 1 package com.yeepay.sxf.template14;
 2 
 3 import java.util.Map;
 4 
 5 /**
 6  * 适配器
 7  * 继承源数据的实现类,
 8  * 实现目标类的接口
 9  * @author sxf
10  *
11  */
12 public class UserInfoAdapter extends OutUserInfoimpl implements IUserInfo{
13 
14     @Override
15     public String getNameById(Integer id) {
16         //转换适配    
17         Map<String, String> map=super.getNameById(String.valueOf(id));
18         //获取名字
19         String name=map.get(String.valueOf(id));
20         return name;
21     }
22 
23     @Override
24     public String getAddressBydName(String name) {
25         //转换适配
26         Map<String, String> map=super.getAddressByName(name);
27         //获取地址
28         String address=map.get(name);
29         return address;
30     }
31 
32     
33 }
View Code

【6】客户端测试

 1 package com.yeepay.sxf.template14;
 2 /**
 3  * 客户端测试
 4  * 以前业务类,从本数据库获取用户信息
 5  * 现在的业务,要从别的系统获取用户信息。别的系统的用户信息的接口返回值不兼容。
 6  * 用适配器模式兼容别的用户系统的接口
 7  * @author sxf
 8  *
 9  */
10 public class ClientTest {
11 
12     public static void main(String[] args) {
13         //原有业务
14         IUserInfo userInfo=new UserInfo();
15         //获取名字
16         String nameString=userInfo.getNameById(1234);
17         //获取地址
18         String addresString=userInfo.getAddressBydName(nameString);
19         System.out.println("ClientTest.main()"+nameString);
20         System.out.println("ClientTest.main()"+addresString);
21         
22         
23         
24         //现有变动业务,要远程RMI调用别的系统的用户
25         IUserInfo userInfo2=new UserInfoAdapter();
26         //获取别的系统的名字
27         String nameString2=userInfo2.getNameById(12345);
28         //获取别的系统的地址
29         String addreString2=userInfo2.getAddressBydName(nameString2);
30         System.out.println("ClientTest.main()"+nameString2);
31         System.out.println("ClientTest.main()"+addreString2);
32         
33     }
34 }
View Code

 

相关文章
重构旧代码的秘诀:用设计模式 - 适配器模式(Adapter)给Java项目带来新生
【4月更文挑战第7天】适配器模式是解决接口不兼容问题的结构型设计模式,通过引入适配器类实现目标接口并持有不兼容类引用,实现旧代码与新接口的协作。适用于处理兼容性问题、整合遗留代码和集成第三方库。应用时,识别不兼容接口,创建适配器类转换方法调用,然后替换原有引用。注意保持适配器简单、使用组合和考虑扩展性。过度使用可能导致系统复杂和维护成本增加,应谨慎使用。
134 4
「全网最细 + 实战源码案例」设计模式——适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,通过引入适配器类将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协作的类能够协同工作。适配器模式分为类适配器和对象适配器两种,前者通过多重继承实现,后者通过组合方式实现,更常用。该模式适用于遗留系统改造、接口转换和第三方库集成等场景,能提高代码复用性和灵活性,但也可能增加代码复杂性和性能开销。
76 28
前端必须掌握的设计模式——适配器模式
适配器模式是一种结构型设计模式,用于使接口不兼容的对象能够相互合作。通过在客户端和系统之间引入一个“中间层”适配器,将不同类型的输入数据转换为系统能处理的标准格式,减轻系统的负担,提高扩展性和可维护性。例如,MacBook的扩展坞将多种接口(如HDMI、USB)转换为Type-C接口,实现多接口兼容。
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
Java设计模式-适配器模式(8)
Java设计模式-适配器模式(8)
Java设计模式之适配器模式
这篇文章详细讲解了Java设计模式中的适配器模式,包括其应用场景、实现方式及代码示例。
85 0
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
【六】设计模式~~~结构型模式~~~适配器模式(Java)
文章详细介绍了适配器模式(Adapter Pattern),这是一种结构型设计模式,用于将一个类的接口转换成客户期望的另一个接口,使原本不兼容的接口能够一起工作,提高了类的复用性和系统的灵活性。通过对象适配器和类适配器两种实现方式,展示了适配器模式的代码应用,并讨论了其优点、缺点以及适用场景。
适配器模式-大话设计模式
适配器模式-大话设计模式
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等