只要一个方法操作的是类而非接口,那么你就只能使用这个类及其子类。如果你想要将这个方法应用于不在此继承结构中的某个类,那么你就会倒大霉了。接口可以在很大程序上放宽这种限制,因此它使得我们可以编写可复用性更好的代码
首先看,通过类的继承实现的一个程序
class Processor{
public String name(){
return getClass().getSimpleName();
}
Object process(Object input){
return input;
}
}
class Upcase extends Processor{
String process(Object input){
return ((String)input).toUpperCase();
}
}
class Downcase extends Processor{
String process (Object input){
return ((String)input).toLowerCase();
}
}
class Splitter extends Processor{
String process(Object input){
return Arrays.toString(((String)input).split(" "));
}
}
public class Apply {
public static String s = "Disagredment with beliefs is by definition incorrect";
public static void process(Processor p, Object s){
System.out.println("Using Processor "+ p.name());
System.out.println(p.process(s));
}
public static void main(String[] args) {
process(new Upcase(),s);
process(new Downcase(),s);
process(new Splitter(),s);
}
}
这个例子很简单,只是把字符串转换为大写,小写和以空格拆分的字符串。值得注意的是负责转换的类Upcase, Downcase和Splitter都是继承于Processor的,而Processor是一个普通的类。咋一看是没问题的,但是要想通过复用把以下的别的类似的程序就不方便了
class Waveform{
private static long counter;
private final long id = counter++;
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;
}
@Override
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 lowCutoff,highCutoff;
public BandPass(double lowCut, double highCut){
lowCutoff = lowCut;
highCutoff = highCut;
}
}
因为在Apply.process()方法在传入的是Processor类,而Filter的创建者压根不清楚它将要被用作Processor。也许你会认为通过继承Process就把问题解决了,但是你会发现Filter.process和Process.process的方法签名是不一样的,那就是说Filter并没有覆盖Process的方法,这样将会导致不安全性(Filter因继承而多了一个不在设计范围内的方法)。因此使得代码复用就很难了,主要的原因是Apply.process()和Process之间的耦合太紧了。如果把Processor改为接口,这些限制就会变得松动了
interface Processor {
String name();
Object process(Object input);
}
//把导出类的name方法抽取出来单独设置一个abstract类
abstract class StringProcessor implements Processor{
public String name(){
return getClass().getSimpleName();
}
public abstract String process(Object input);
}
class Upcase extends StringProcessor {
@Override
public String process(Object input) {
return ((String)input).toUpperCase();
}
}
class Splitter extends StringProcessor{
@Override
public String process(Object input) {
return Arrays.toString(((String)input).split(" "));
}
}
class Downcase extends StringProcessor {
@Override
public String process(Object input) {
return ((String)input).toLowerCase();
}
}
public class Apply {
public static String s = "Disagredment with beliefs is by definition incorrect";
public static void process(Processor p, Object s){
System.out.println("Using Processor "+ p.name());
System.out.println(p.process(s));
}
public static void main(String[] args) {
process(new Upcase(), s);
process(new Downcase(),s);
process(new Splitter(),s);
}
}
这种我们就可以通过实现接口而在复用的基础上加入Filter了
abstract class Filter implements Processor {
public String name() {
return getClass().getSimpleName();
}
public abstract Waveform process(Object input);
}
class BandPass extends Filter{
double lowCutoff,highCutoff;
public BandPass(double lowCut, double highCut){
lowCutoff = lowCut;
highCutoff = highCut;
}
@Override
public Waveform process(Object input) {
return (Waveform) input;
}
}
class HighPass extends Filter{
double cutoff;
public HighPass(double cutoff){
this.cutoff = cutoff;
}
@Override
public Waveform process(Object input) {
return (Waveform) input;
}
}
class LowPass extends Filter{
double cutoff;
public LowPass(double cutoff){
this.cutoff = cutoff;
}
@Override
public Waveform process (Object input){
return (Waveform) input;
}
}
public class Apply {
public static String s = "Disagredment with beliefs is by definition incorrect";
public static void process(Processor p, Object s){
System.out.println("Using Processor "+ p.name());
System.out.println(p.process(s));
}
public static void main(String[] args) {
//process(new Upcase(), s);
//process(new Downcase(),s);
//process(new Splitter(),s);
Waveform w = new Waveform();
process(new LowPass(1.0),w);
process(new HighPass(3.0),w);
process(new BandPass(1.0,2.0),w);
}
}
上面的例子很好说明了,不用修改原程序(当然Filter还是要改的),可以直接通过复用接口Processor和Apply.process()。然后有的时候Filter并不是可以修改的,或者你得到的只是一个类库,这个时候可以使用Adaptor设计模式
//Filter不能修改
class Filter{
public String name(){
return getClass().getSimpleName();
}
// @Override
public Waveform process(Waveform input){
return input;
}
}
//Filter的Adapter
class FilterAdapter implements Processor {
Filter filter;
public FilterAdapter (Filter filter){
this.filter = filter;
}
public String name() {
return filter.name();
}
public Waveform process(Object input) {
return filter.process((Waveform) input);
}
}public class Apply {
public static String s = "Disagredment with beliefs is by definition incorrect";
public static void process(Processor p, Object s){
System.out.println("Using Processor "+ p.name());
System.out.println(p.process(s));
}
public static void main(String[] args) {
Waveform w = new Waveform();
process(new FilterAdapter(new chapter9.LowPass(1.0)),w);
process(new FilterAdapter(new chapter9.HighPass(3.0)),w);
process(new FilterAdapter(new chapter9.BandPass(1.0,2.0)),w);
}
}
在这种使用适配器的方式中,FilterAdapter的构造器接受你所拥有的接口Filter,然后生成具有你所需要的Processor接口的对象。在FilterAdapter中还使用了代理