Java设计模式之适配器模式(Adapter)
这个总结的挺好的,为了加深印象,我自己再尝试总结一下
1.定义:
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
(太官方了,不太好理解,
其实就是要用到两个不相关的类/接口,但是又没有源代码,或者不想修改源代码,而增加一个类来完成合并使用的目的)
2.实现这个目的有两个方法,继承或者组合
2.1.使用继承(就是所谓的类适配器模式)
2.2.使用组合(所谓的对象适配器模式)
案例: 公司招员工,要求会讲中、英、法、日四国语言,同时还很会编程的员工。
招聘要求类 JobNeedSkill 接口:
1 package design.pattern.adapter2; 2 3 public interface JobNeedSkill { 4 void speakChinese(); 5 void speakEnglish(); 6 void speakJapanese(); 7 void speakFrench(); 8 void goodCoding(); 9 }
而这里有个工人,技术超一流,可惜只会说中文。
Worker类:
1 package design.pattern.adapter2; 2 3 public class Worker { 4 public void goodCoding(){ 5 System.out.println("我编程也挺牛的哦"); 6 } 7 8 public void speakChinese(){ 9 System.out.println("我只会说中文呢,能不能请我啊"); 10 } 11 }
招聘测试类 Test:
1 package design.pattern.adapter2; 2 3 public class Test { 4 //招聘员工 5 public static void hireWorker(JobNeedSkill worker){ 6 System.out .println("恭喜你,你被录用了,展示一下你的技能吧"); 7 8 System.out .println("==============================="); 9 worker.speakChinese(); 10 worker.speakEnglish(); 11 worker.speakFrench(); 12 worker.speakJapanese(); 13 worker.goodCoding(); 14 } 15 16 public static void main(String[] args){ 17 //我是个只会说中文的工人 ,但我编程好 18 Worker me = new Worker(); 19 20 //我们需要一个会说四国语言的员工 21 // hireWorker(me);//直接招聘是不行了,再给他配个步步高点读机吧 22 23 /* 24 * 以上代码为初始状态,后面的代码是后面根据需求增加的 25 * */ 26 27 //有步步高点读机,这是使用了继承的方式,类的适配模式 28 TheManHasBuBuGao bbg = new TheManHasBuBuGao(); 29 hireWorker(bbg); 30 31 System.out.println("*****************\r\n"); 32 //这个自带助理的,是使用了组合的方式,是对象的适配模式 33 WorkerHasAssistant gfs = new WorkerHasAssistant(me); 34 hireWorker(gfs); 35 } 36 37 }
很明显,一开始的时候发现,尽管这个人技术很牛,但是只会说中文这一点,实在让人觉得可惜,
别说我们公司不能招聘了,就连eclipse都提示错误了:
不过他的技术的确非常符合我们公司的需要,怎么办呢,咋取舍呢······
如果,如果他有一台 “步步高点读机呢”
TheManHasBuBuGao类:
1 package design.pattern.adapter2; 2 //这里使用了继承的方式 3 public class TheManHasBuBuGao extends Worker implements JobNeedSkill{ 4 5 @Override 6 public void speakJapanese() { 7 System.out.println("妈妈再也不用担心我的日语了"); 8 } 9 10 @Override 11 public void speakFrench() { 12 System.out.println("哪里不会就点哪里,这样法语也随便搞定了"); 13 } 14 15 @Override 16 public void speakEnglish() { 17 System.out.println("So Easy."); 18 } 19 20 }
这样问题就解决了,步步高点读机就是好!
不过他说他没有步步高点读机,但是他有一个贴身翻译助理
WorkerHasAssistant类:
1 package design.pattern.adapter2; 2 3 public class WorkerHasAssistant implements JobNeedSkill{ 4 //这个人有自己的助理翻译,这里是使用了组合的方式 5 private Worker worker; 6 7 //在构造方法中传进来 8 public WorkerHasAssistant(Worker worker){ 9 this.worker = worker; 10 } 11 12 @Override 13 public void goodCoding() { 14 worker.goodCoding(); 15 } 16 @Override 17 public void speakChinese() { 18 //worker会说,直接用worker 19 worker.speakChinese(); 20 } 21 22 @Override 23 public void speakEnglish() { 24 //英语他不会说,这就要助手出马翻译了 25 System.out.println("我是他的翻译,他说 Hello World."); 26 } 27 28 @Override 29 public void speakJapanese() { 30 //日语他也不会说,这还是要助手出马翻译了 31 System.out.println("八嘎"); 32 } 33 34 @Override 35 public void speakFrench() { 36 //每错,他英语也不行 37 System.out.println("He can say English too."); 38 } 39 40 41 }
最后运行的效果是:
把文章看完是个好习惯,
在最后还要特别说明一下,适配器模式还有一种默认缺省的用法,这个目的跟上面的略微不同,但做法是一致的,
都是增加了一个适配类,哈哈(别跟别的设计模式搞混了哦,同时这种用法在Swing开发里经常用到)
Skill 接口:
1 package design.pattern.adapter2; 2 3 public interface Skill { 4 void sing(); 5 void dance(); 6 void fly(); 7 void cry(); 8 //.......一大堆方法 9 }
如果 Person类直接实现 Skill接口,就会变成这样:
1 package design.pattern.adapter2; 2 3 public class Person implements Skill{ 4 5 @Override 6 public void sing() { 7 // TODO Auto-generated method stub 8 9 } 10 11 @Override 12 public void dance() { 13 // TODO Auto-generated method stub 14 15 } 16 17 @Override 18 public void fly() { 19 // TODO Auto-generated method stub 20 21 } 22 23 @Override 24 public void cry() { 25 // TODO Auto-generated method stub 26 27 } 28 29 }
必须同时实现Skill接口中的所有方法,但其实我们关注的只是其中某一个方法而已,
所以,这时候就可以增加一个中间类SkillAdapter,这个类也实现了Skill接口,并实现了所有方法,不过是空实现:
1 package design.pattern.adapter2; 2 3 public class SkillAdapter implements Skill{ 4 5 @Override 6 public void sing() { 7 // TODO Auto-generated method stub 8 9 } 10 11 @Override 12 public void dance() { 13 // TODO Auto-generated method stub 14 15 } 16 17 @Override 18 public void fly() { 19 // TODO Auto-generated method stub 20 21 } 22 23 @Override 24 public void cry() { 25 // TODO Auto-generated method stub 26 27 } 28 29 }
而我们在继承这个中间类(Adapter),再重写我们所关注的方法就可以了,而无需做过多无谓的操作:
1 package design.pattern.adapter2; 2 3 public class NewPerson extends SkillAdapter{ 4 public void sing(){ 5 System.out.println("我只会唱歌,别的我都不会了"); 6 } 7 }
最后再总结一下:
因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构(也就是去改代码),
除了这种默认缺省的适配器外,前面的例子都是在没办法情况下的办法而已。