接口解耦

例子摘自 Thingking in java8第10章接口之完全解耦一节.

https://lingcoder.github.io/OnJava8/#/book/10-Interfaces?id=%e5%ae%8c%e5%85%a8%e8%a7%a3%e8%80%a6

刚开始Processor是个父类,

class Processor {
  public String name() {
    return getClass().getSimpleName();
  }

  public Object process(Object input) {
    return input;
  }
}

下面一堆子类继承他,然后将声明的父类传到Applicator类的方法中.

public class Applicator {
  public static void apply(Processor p, Object s) {
    System.out.println("Using Processor " + p.name());
    System.out.println(p.process(s));
  }
}

 

这样做Processor就只能处理某一种类型的对象.没有解耦.

现在有类似方法的类Filter出现了,想要复用Applicator类代码.但是因为apply方法接收的是Processor类所以没法复用.

class Filter {

  public String name() {
    return getClass().getSimpleName();
  }

  public Waveform process(Waveform input) {
    return input;
  }
}

 

如果Processor是一个接口,apply方法接收一个接口参数,那么就不会跟具体的类绑定,实现了解耦.

interface Processor {

  default String name() {
    return getClass().getSimpleName();
  }

  Object process(Object input);
}

 

Applicator改写成接收接口参数的形式:

Applicator还是个类,它里面保有固定的具体的方法代码.

虽然apply方法里参数是接口形式的,但实际要传实现类进去

class Applicator {
                            //现在Processor是接口
  public static void apply(Processor p, Object s) {
    System.out.println("Using Processor " + p.name());
    System.out.println(p.process(s));
  }
}

现在的Processor是一个抽象的笼统的”处理器”角色,

可以根据不同任务创建不同的,特定方向的”子处理器”角色.

子类型接口继承父类型接口(接口不能继承类,否则会获得父类的构造方法,而接口只允许有静态变量,默认方法或抽象方法)

interface StringProcessor extends Processor {
  @Override
  String process(Object input); // [1]
  String S = "If she weighs the same as a duck, she's made of wood"; // [2]
}

 

然后根据子接口创建更具体的实现类Upcase来处理任务.

class Upcase implements StringProcessor {
  // 返回协变类型
  @Override
  public String process(Object input) {
    return ((String) input).toUpperCase();
  }
}

 

现在Applicator可以工作了:

public class test{
  static void main(String[] args) { // [3]
    Applicator.apply(new Upcase(), S);
    Applicator.apply(new Downcase(), S);
    Applicator.apply(new Splitter(), S);
  }
}

 

但是现实情况是很多类是已有的或别人创建的,只能拿来用但是不能修改.

所以上面的情况可以再改成适配器设计模式.适配器允许代码接受已有的接口产生需要的接口.

 

这里有一个Filter类的子类:

public class HighPass extends Filter {
  double cutoff;

  public HighPass(double cutoff) {
    this.cutoff = cutoff;
  }

  @Override
  public Waveform process(Waveform input) {
    return input;
  }
}

 

改成下面这个样子:

public class FilterProcessor {
  public static void main(String[] args) {
    Waveform w = new Waveform();
    Applicator.apply(new FilterAdapter(new LowPass(1.0)), w);
    Applicator.apply(new FilterAdapter(new HighPass(2.0)), w);
    Applicator.apply(new FilterAdapter(new BandPass(3.0, 4.0)), w);
  }
}
public class LowPass extends Filter {
  double cutoff;

  public LowPass(double cutoff) {
    this.cutoff = cutoff;
  }

  @Override
  public Waveform process(Waveform input) {
    return input; // Dummy processing 哑处理
  }
}

 

在StringProcessor的例子里,Upcase类里的方法是String自带的.无需指定其他对象.

但是Waveform的例子里,处理波的对象是Filter,需要从外面引入.

怎么调和这种差异呢?

 

apply方法的参数已经定义好了,一个处理者(接口),一个被处理者.

解决办法是:对于waveform例子,引入适配器adapter这一对象去引入Filter.适配器实现了接口.可以满足apply的参数要求.

 

简单来说,stringProcessor的例子里,只需要2个参数,处理者和被处理对象,调的是对象的方法.

wave的例子里调的是处理者的方法.

 

apply方法的第一个参数就有了不一致的情形.也就是Processor里的process方法是有区别的.

stringProcessor例子里的process方法只要被处理着本身一个参数,

wave例子里需要引入处理者,

但是process方法是固定的.不能从入参去考虑传所需要的参数,所以只能另外引入需要的变量.

适配器就是通过构造方法让用户传入需要的参数对象而已.

 

三孔插头和两孔插座的问题.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值