Java 设计模式 接口型模式 之 适配器Adapter模式 (二)

适配器模式的意图 : 使用不同接口的类所提供的服务为客户端提供其所希望的接口;

-- 问题解决场景 : 在 类A 中实现了接口中的抽象方法, 客户端B 已经定义好了方法的调用, 但是调用的方法 与 类A 中的方法名不同, 这时我们就需要适配器模式了;

-- eg : 类A 实现了接口A1, 类B 实现了接口B1, 这里C调用 A 和 B 希望 A 和 B 能提供相同方法的接口, 这时我们需要使用适配器模式;



1. 接口适配



(1) 接口适配简介


接口适配 : 

-- 问题场景 : 客户端需要调用 客户端类接口 中提供的 requiredMethod()的方法, 但是工具类中只提供了一个 existMethod() 方法, 显然客户端接口 与 工具类中提供的方法名称不匹配;

-- 适配方案 :  创建一个 适配器类, 适配现有的代码 工具类,  该类实现客户端接口的 requiredMethod()抽象方法, 与客户端接口是实现关系, 同时该实现类继承 工具类, 可以调用工具类中的方法, 与工具类的关系是 继承关系;

-- 方法委托 : 通过接口适配, 就将 客户端类的requiredMethod() 方法 委派给了 existMethod()方法;





(2) 接口适配实例


.

接口适配需求 : 

-- 客户端提供接口 : 需要研发一种M1坦克, 需要实现接口 getCaliber() 获取火炮口径, fire() 开火, run()移动 等方法; 

-- 现有接口 : 现有的坦克 有 getGunCaliber() 获取火炮口径, GunFire() 火炮开火, Move() 移动 等方法;

-- 适配要求 : 写一个适配类, 这个类实现 Panzer 接口继承 Tanker 类, 将Panzer接口的动作委托给 Tanker 类;





接口类 : 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package shuliang.han.displaytest;  
  2.   
  3. public interface Panzer {  
  4.   
  5.     public double getCaliber();  
  6.     public void fire();  
  7.     public void run();  
  8.       
  9. }  

实体类  : 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package shuliang.han.displaytest;  
  2.   
  3.   
  4. public class Tanker {  
  5.   
  6.     private double caliber = 125.0;  
  7.       
  8.     public double getGunCaliber() {  
  9.         return caliber;  
  10.     }  
  11.       
  12.     public void gunFire() {  
  13.         System.out.println("Fire in the hole !!!");  
  14.     }  
  15.       
  16.     public void move() {  
  17.         System.out.println("Move move !!");  
  18.     }  
  19.       
  20. }  


分析 : 

-- 名称不匹配 : Tanker类中的方法可以执行 Panzer 接口中需要的动作, 但是它们的方法名称不匹配;

-- 变量维护 : 如果创建一个 M1A2SEP 类, 需要在类中维护一个 Tank 对象, 在 Panzer 实现类中调用 对应的 Tank 对象方法;


M1A2SEP 类 : 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package shuliang.han.displaytest;  
  2.   
  3. public class M1A2SEP extends Tanker implements Panzer  {  
  4.   
  5.     @Override  
  6.     public double getCaliber() {  
  7.         return getGunCaliber();  
  8.     }  
  9.   
  10.     @Override  
  11.     public void fire() {  
  12.         gunFire();  
  13.     }  
  14.   
  15.     @Override  
  16.     public void run() {  
  17.         move();  
  18.     }  
  19.   
  20. }  



接口适配总结 : 

-- 客户端接口存在 : 如果客户端接口中定义了客户端所期待的行为, 可以运用适配器模式, 适配器继承现有类, 并实现客户端接口;

-- 客户端接口不存在 : 如果客户端没有定义接口, 可以使用对象适配器, 对象适配器相当于 子类适配器;



2. 对象适配


(1) 对象适配简介


类适配 : 上面的接口适配方式就是类适配, 适配器类需要 实现客户端接口继承 现有实体类;

对象适配 : 对象适配器采用了委派, 并非是继承; 创建一个对象适配器, 继承客户端类, 在类中维护一个现有类实例对象, 满足客户端类需求方法; 

-- 需要场景 : 如果适配的客户端方法没有被定义在接口中, 就需要对象适配;




对象适配的方法 : 

-- 适配器类继承客户端类 : 对象适配的适配器类 继承客户端类对象, 适配器类 的 实例 也是 客户端类的实例, 因为适配器类是客户端类的子类;  

-- 适配器类使用现有类 : 适配器类中定义一个 现有类对象作为成员变量, 通过调用 现有类对象中的方法 来实现客户端类方法的需求;


(2) 对象适配实例


客户端类 : 现在有客户端类 Panzer 装甲车, 提供 获取火炮口径方法 getCaliber(), 移动方法 run(), 开火方法 fire(); 

现有类 : 现有类 Tank 坦克, 提供 获取火炮口径方法 getGunCaliber(), 移动方法 move(), 开火方法 gunFire();


客户端类代码 : 客户端类代码中没有指定建模所需的接口;

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package shuliang.han.adapter;  
  2.   
  3. public class Panzer {  
  4.   
  5.     public double getCaliber(){  
  6.         return 0;  
  7.     }  
  8.       
  9.     public void fire(){  
  10.         //TODO  
  11.     }  
  12.       
  13.     public void run(){  
  14.         //TODO  
  15.     }  
  16. }  

现有类代码  : 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package shuliang.han.adapter;  
  2.   
  3. public class Tank {  
  4.   
  5.     private double caliber = 125.0;  
  6.       
  7.     public double getGunCaliber(){  
  8.         return caliber;  
  9.     }  
  10.       
  11.     public void gunFire() {  
  12.         System.out.println("Fire in the hole !!!");  
  13.     }  
  14.       
  15.     public void move() {  
  16.         System.out.println("Move Move !!!");  
  17.     }  
  18. }  


UML图 



适配器类 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package shuliang.han.adapter;  
  2.   
  3. public class M1A2 extends Panzer {  
  4.       
  5.     private Tank tank;  
  6.       
  7.     public M1A2() {  
  8.         tank = new Tank();  
  9.     }  
  10.       
  11.     @Override  
  12.     public double getCaliber() {  
  13.         return tank.getGunCaliber();  
  14.     }  
  15.   
  16.     @Override  
  17.     public void fire() {  
  18.         super.fire();  
  19.         tank.gunFire();  
  20.     }  
  21.       
  22.     @Override  
  23.     public void run() {  
  24.         super.run();  
  25.         tank.move();  
  26.     }  
  27.       
  28. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值