eric-1001c

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  3 随笔 :: 45 文章 :: 12 评论 :: 0 Trackbacks
只要一个方法操作的是类而非接口,那么你就只能使用这个类及其子类。如果你想要将这个方法应用于不在此继承结构中的某个类,那么你就会倒大霉了。接口可以在很大程序上放宽这种限制,因此它使得我们可以编写可复用性更好的代码
首先看,通过类的继承实现的一个程序
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中还使用了代理

posted on 2007-07-12 19:23 Eric-1001c 阅读(2500) 评论(3)  编辑  收藏 所属分类: ThinkingInJava

评论

# re: 接口之完全解耦 2009-02-01 09:46 holmes
thinking in java原文+源代码  回复  更多评论
  

# re: 接口之完全解耦[未登录] 2013-06-02 19:39 王杰
一直以来 我的java基础不是很好 最近在学习java基础 看到继承和接口这块 令我实在不解的是我为什么在这个例子中要用interface ,下面这样写不行吗??好像不用接口 thinking in java中也是这么讲的 我实在不解

class FilterConver extends Processor{
Filter filter;
public FilterConver(Filter filter) {
this.filter = filter;
}
@Override
Waveform process(Object input) {
// TODO Auto-generated method stub
return filter.process((Waveform)input);
}
}  回复  更多评论
  

# re: 接口之完全解耦[未登录] 2013-06-02 19:40 王杰
如果可以解释下直接QQ我吧 120482338 多谢哈   回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: