一、介绍 概念:一个类的接口转换成客户端希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。即根据已有的接口,生成想要的接口。
先看下面这个小例子体会一下适配器模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class AppTest { public static void main (String[] args) { Calculate calculate = new Calculate(); CalcAdapter calcAdapter = new CalcAdapter(calculate); int add = calcAdapter.add(1 , 2 , 3 ); System.out.println(add); } } class Calculate { public int add (int a, int b) { return a + b; } } class CalcAdapter { private Calculate calculate; public CalcAdapter (Calculate calculate) { this .calculate = calculate; } public int add (int a, int b, int c) { return calculate.add(a, calculate.add(b, c)); } }
二、实例 该章节中对适配器模式的讲解,采用Java编程思想的实例,进行介绍。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 class Processor { public String name () { return getClass().getSimpleName(); } Object process (Object input) { return input; } } class Upcase extends Processor { @Override String process (Object input) { return ((String) input).toUpperCase(); } } class DownCase extends Processor { @Override String process (Object input) { return ((String) input).toLowerCase(); } } class Splitter extends Processor { @Override String process (Object input) { return Arrays.toString(((String) input).split(" " )); } } class Apply { public static void process (Processor p, Object s) { System.out.println("Using Process: " + p.name()); System.out.println(p.process(s)); } } public class AppTest { public static void main (String[] args) { String s = "How are you" ; Apply.process(new Upcase(), s); Apply.process(new DownCase(), s); Apply.process(new Splitter(), s); } } === 结果 === Using Process: Upcase HOW ARE YOU Using Process: DownCase how are you Using Process: Splitter [How are you]
该段代码中,主要是为了复用Processor
类中的process
方法,对process的方法采用三种不同实现方式,即设计三个不同的子类。
现在又发现了一个跟process
功能相似的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class Waveform { private static long counter; private final long id = counter++; @Override public String toString () { return "waveform" + id; } } class Filter { public String name () { return getClass().getSimpleName(); } public Waveform process (Waveform input) { return input; } } class LowPass extends Filter { double cutoff; public LowPass (double cutoff) { this .cutoff = cutoff; } public Waveform process (Waveform input) { return input; } } class HighPass extends Filter { double cutoff; public HighPass (double cutoff) { this .cutoff = cutoff; } public Waveform process (Waveform input) { return input; } } class BandPass extends Filter { double cutoff; public BandPass (double cutoff) { this .cutoff = cutoff; } public Waveform process (Waveform input) { return input; } }
从这段代码中,我们可以看到Filter
和前面我们自己定义的Processor
类似,同样的有三个子类也同Processor
的子类。
此时,我们如果想要复用Apply
的方法,参数却无法传入。因为,Apply
参数接收的是Processor
类及其子类。这个时候,你肯定想,那就直接将Filter
继承Processor
类,让其成为子类不就好了?但是,不要忘记,Filter
代码是别人的代码,我们无法对其进行修改。同时,即使进行了修改,那也违反了开闭原则 。
所以我们需要用接口的方式,让Apply接收的是接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 interface Processor { String name () ; Object process (Object input) ; } abstract class AbstractProcess implements Processor { @Override public String name () { return getClass().getSimpleName(); } } class Upcase extends AbstractProcess { @Override public String process (Object input) { return ((String) input).toUpperCase(); } } class DownCase extends AbstractProcess { @Override public String process (Object input) { return ((String) input).toLowerCase(); } } class Splitter extends AbstractProcess { @Override public String process (Object input) { return Arrays.toString(((String) input).split(" " )); } }
在上面中,我们将Process设计成了接口,并且使用了一个AbstractProcess抽象类,实现这个接口,再用子类去继承这个抽象类。设计这个抽象类的原因是,子类如果直接实现Process
接口,那么name()
这个方法都是重复实现,所以直接使用抽象类 进行该方法的实现,即对一些固定功能进行实现,再设计子类直接继承这个抽象类对process
方法进行自己所需要的实现。所以也能看见,抽象类是对接口中固定功能的实现进行抽取,即定义出一些模板方法,这样子类就不需要进行重复实现了。
现在继续看Apply类:
1 2 3 4 5 6 class Apply { public static void process (Processor p, Object s) { System.out.println("Using Process: " + p.name()); System.out.println(p.process(s)); } }
此时接收的参数Process是接口,表明只要是实现了该接口的类及其实现类的子类都能被传入。那么我们该如何传入这个参数呢?即采用适配器模式。设计一个适配器去实现该接口,将被适配的类和适配器进行关联,而适配器作为接口的具体的实现,这样适配器就能够被作为参数进行传入,而具体使用的是被适配类的方法。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class FilterAdapter implements Processor { private Filter filter; public FilterAdapter (Filter filter) { this .filter = filter; } @Override public String name () { return filter.name(); } @Override public Object process (Object input) { Waveform process = filter.process((Waveform) input); return process; } }
此时我们就可以直接复用process
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class AppTest { public static void main (String[] args) { String s = "How are you" ; Apply.process(new FilterAdapter(new LowPass(1 )), new Waveform()); Apply.process(new FilterAdapter(new HighPass(1 )), new Waveform()); Apply.process(new FilterAdapter(new BandPass(1 )), new Waveform()); } } ===结果=== Using Process: LowPass waveform: [0 ] Using Process: HighPass waveform: [1 ] Using Process: BandPass waveform: [2 ]
适配器实现接口而没有继承类的原因是,如果使用继承,后面就不能再继承其它类了,而接口可以进行多实现,也可以看出接口比继承有着更宽松的规则(不仅可以是接口的实现类,其实现类的子类也能够作为参数进行传递)。
如果,我们不使用适配器,而是直接使用这个类会发生什么?
1 2 3 4 5 6 7 8 9 10 11 12 public class AppTest { public static void main (String[] args) { Filter lowPass = new LowPass(1 ); System.out.println(lowPass.name()); System.out.println(lowPass.process(new Waveform())); Filter highPass = new HighPass(1 ); System.out.println(highPass.name()); System.out.println(highPass.process(new Waveform())); Filter bandPass= new BandPass(1 ); System.out.println(bandPass.name()); System.out.println(bandPass.process(new Waveform())); }
无法使用Apply类提供的方法,明明所实现的都是一样的,可还需要多写一套代码,使用适配器,将需要被使用类的接口,转换成能够被适配的接口。
三、使用步骤 自定义适配器类,适配器继承被适配的接口,自定义的适配器类中组合被适配的类,在实现的方法中调用被适配类的方法。