I want to fly higher
programming Explorer
posts - 114,comments - 263,trackbacks - 0
1.接口和内部类我们提供了一种将接口与实现分离的更加结构化的方法。
2.抽象类,普通的类与接口之间的一种中庸之道。尽管在构建具有某些未实现方法的类时,你的第一想法可能是创建接口,但是抽象类仍然是用于此目的的一种重要而必须的工具。因为你不可能总是使用纯接口。
     1.通用接口,建立诸如Instrument(乐器)这个通用接口的唯一理由是,不同的子类可以用不同的方式表示此接口。通用接口建立起来一种基本形式,以此表示所有导出类的共同部分。
     2.另一种说法是将Instrument类称作抽象基类或简称抽象类。如果我们只有一个像Instrument的抽象类,那么该类的对象几乎没有任何意义。我们创建抽象类是希望通过这个通用接口操纵一系列类。因此    Instrument只是表示了一个接口,没有具体的实现内容,因此创建一个Instrument对象没有什么意义,并且我们还可能想阻止使用者这样做。通过让Instrument中的所有方法都产生错误,就可以实现这个目的。但是这样做会将错误信息延迟到运行时才获得,并且需要在客户端进行可靠,详尽的测试。所以最好是在编译时捕获这些问题->Java提供了抽象方法的机制,不完整的,仅有声明而没有方法体,如 abstract void f();
     3.包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的,否则编译器报错。如果一个抽象类不完整,那么当我们试图产生该类的对象时,编译器会怎么处理。由于为抽象类创建对象是不安全的,所以我们会从编译器那里得到一条出错信息。这样,编译器会确保抽象类的纯粹性,我们不必担心会误用它。
     4.如果从一个抽象类继承,并想创建该类的对象,那么就必须为基类的所有抽象方法提供方法定义,如果不这样做,可以选择不做,那么导出类也是抽象类,且编译器会强制我们用abstract关键字来限制这个类。
     5.我们也可能创建一个没有任何抽象方法的抽象类,考虑这种情况,如果有一个类,让其包含任何abstracat方法都显得没有任何实际意义,而且我们也想阻止产生这个类的任何对象,那么这样做就很有用了。
     6.创建抽象类和抽象方法很有用,因为他们可以使类的抽象性明确起来,并告诉用户和编译器打算怎么样来使用他们。抽象类还是很有用的重构工具,因为他们使得我们可以很容易的将公共方法沿着继承层次向上移动。
3.interface关键字使抽象的概念更向前迈进了一步。abstract关键字允许人们在类中创建一个或多个没有任何定义的方法,提供了接口部分,而没有提供任何相应的具体实现。这些实现是由类的继承者创建的.interface这个关键字产生一个完全抽象的类,它根本就没有提供任何具体实现。接口只提供了形式,而未提供任何具体实现。
     1.一个接口表示,所有实现了该特定接口的类看起来都像这样。因此任何使用某特定接口的代码都知道可以调用该接口的哪些方法,而且仅需要知道这些。因此接口被用来建立类与类之间的协议。protocol.
     3.interface不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能够被向上转型为多种基类的类型,来实现某种类似多重继承变种的特性。
     4.接口也可以包含域,不过这些域隐式的是static和final的。可以选择在接口中显示的将方法声明为public的,但即使你不这么做,他们也是public的,因此,当要实现一个接口时,在接口中被定义的方法必须被定义为public的。否则他们只得到默认的包访问权限,这样在方法被继承的过程中 ,其可访问权限就被降低了。这是Java编译器所不允许的。
      注:不仅仅是接口,对于继承覆盖的方法也不能降低可访问权限,即 Cannot reduce the visibility of the inherited method.但是我们可以增加可访问权限,比如基类方法是default,而导出类的覆盖方法则可以将访问权限提升至public.
4.只要一个方法操作的是类而不是接口,那么你就只能使用这个类及其子类,如果你想要将这个方法应用于不再此继承结构的某个类,那么你就会触霉头了。接口可以在很大程度上放宽这种限制,因此他们可以使我们可以编写可复用性更好的代码。
     1.创建一个能够根据所传递的对象的参数不同而具有不同行为的方法,被称为策略设计模式。这类方法包含的所要执行的算法中固定不变的部分,而策略包含变化的部分,策略就是传递进去的参数对象 ,它包含要执行的代码。
     2.将接口从具体实现中解耦使得接口可以应用于多种不同的具体实现,因此代码也就更具可复用性。
5.接口不仅仅是只是一种更纯粹形式的抽象类,它的目标比这要求更高。因为接口是没有任何具体实现的,也就是说没有任何与接口相关的存储;因此也就无法阻止多个接口的组合。这一点是很有价值的,因为你有时需要去表示“一个x是一个a和一个b以及一个c”。在c++中,组合多个类接口的行为被称作为多重继承(C++菱形问题,即B,C同时继承了接口A,D多重继承B,C,这样在调用A中的方法的时候,无法知道该方法究竟是B中的还是C中的)。它可能会使你背负很沉重的包袱,因为每一个类都有一个具体实现。
      注:Java中接口不会有这样的问题,当你实现多个接口的时候。因为接口是没有实现的,这样菱形问题就不会对编译器造成困扰,因为都是没有实现的。即如接口B和接口C继承结合A,而实现类D实现了接口B和C,此时D的实现类中实现具体方法,因为所有的接口都是无实现的,所以编译器不会困扰,因为调用的肯定是实现的具体类的方法。因为具体类必须实现接口中未实现的方法。当然使用抽象类也是不行的,因为抽象类中也可以定义具体的方法。
     1.当通过一个具体类和多个接口组合到一起的时候,这个具体类必须放在前面,后面跟着的才是接口,否则编译报错。
      :个人觉得这条规定可能是防止歧义的出现,比如正常的形式是A extends B implements C,D 如果换做:A implements C,D extends B的话,肯定会有歧义的,是c或D extends B?所以说编译器强制这样规定(接口可以extends接口的)。
     2.使用接口的核心原因:
          1.为了能够向上转型为多个基类型以及由此而带来的灵活性。
          2.然而使用接口的第二个原因却是与抽象基类相同,防止客户端程序员创建该类的对象,并确保这仅仅是创建一个接口。这就带了一个问题:我们应该使用接口还是抽象类?如果我们要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口。
          3.通过继承来扩展接口
          4.一定要注意组合接口时的名字冲突问题->在打算组合的不同接口中使用相同的方法名通常会造成代码可读性的混乱,因为覆盖,实现,重载令人不愉快的搅在了一起,而且重载方法仅通过返回类型是区分不开的。请尽量避免这种情况。
6.适配接口:
     1.接口最吸引人的原因就是允许同一个接口具有不同的具体实现。在简单的情况下,它的体现形式通常是一个接受接口类型的方法,而该接口的实现和向该方法传递的对象则取决于方法的使用者。因此接口的一种常见用法是策略设计模式。此时你编写一个执行某些操作的方法,而该方法将接受一个同样是你指定的接口,你主要就是要声明,“你可以用任何你想要的对象来调用我的方法,只要你的对象遵循我的接口”。这使你的方法更加灵活,通用并更具复用性。如Scanner的构造器参数Readable接口,通过这种方式,Scanner可以作用于更多的类型,只要你创建一个新类,并且让它成为Readable即可。
 假设你有一个还未实现Readable接口的类B,怎么样才能让Scanner作用于它呢?-使用适配器模式,A extends B implements Readable接口即可。即被适配的类A可以通过继承B和实现Readable的类实现。因此,通过使用interface关键字提供的伪多重继承机制,我们可以生成既是B又是Readable接口的新类A.
  这种方式,我们可以在任何现有类之上添加新的接口,所以这意味着让方法接受接口类型,如{@link Scanner};是一种让任何类都可以对该方法进行适配的方式。这是使用接口而不是类的强大之处。
7.接口中的域:
     因为你放入接口中的任何域都自动是static和final的,所以接口就成为了一种很便捷的用来创建常量组的工具。在Java SE5之前,这是产生于C/C++的enum(枚举类型)具有相同效果的类的唯一途径。有了Java SE5,你就可以使用更加强大而且灵活的enum关键字,因此用接口群组常量已经显得没什么意义了。
     1.初始化接口中定义的域
          1.在接口中定义的域不能是空final,但是可以被非常量表达式初始化。因为域是static的,所以它们就可以在类第一次被加载时初始化。这发生在任何域首次被访问时。
     注:域不是接口的一部分,它们的值被存储在该接口的静态存储区域内。
8.嵌套接口
     1.接口可以嵌套在类中或其他接口中。这揭示了许多非常有趣的特性。
     :嵌套的private接口,实现一个private接口只是一个形式,它可以强制该接口中的方法定义不要添加任何类型信息,也就是说,不允许向上转型。个人理解是因为private接口,所以在外面调用中肯定不能被转型为定义的private接口类型,因为不可见。
      getD方法使我们陷入了一个进退两难的境地,这个问题与private接口有关:它是一个返回private接口引用的public方法。你对这个方法的返回值能做些什么呢?在main中,我们可以看到,数次尝试使用返回值的行为都失败了。只有一种方式可以成功,那就是将返回值交给有权使用它的对象。在本例中,是另一个A通过receiveD来实现的。
 同样,接口之间也可以彼此嵌套。然而,作用于接口中的各种规则,特别是所有的接口元素,都必须是public的,因此嵌套在 另一个接口中的接口自动就是public的,而不能声明为private的。
     :当要实现某个接口时,并不需要实现嵌套在其内部的任何接口,而且private接口不能在定义它之外的类实现。
9.接口与工厂
     1.接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现对象。理论上,通过这种方式,我们的代码将完全与接口的实现分离,这就使得我们可以透明的将某个实现替换为另一个实现。
          1.如果不是用工厂方法,你的代码就必须在某处指定将要创建的Service确切类型,以便调用合适的构造器。为什么我们想要添加这种额外级别的间接性呢?一个常见的原因是想要创建框架:假设你正在创建一个对弈游戏系统,例如,在相同的棋盘上下国际象棋和西洋跳棋,如果Games类,处理逻辑,表示一段复杂的代码,那么这种方式允许你在不同类型的游戏中复用这段代码{@link Games}
          2.下一章我们将会看到另一种更加优雅的工厂实现方式,那就是使用匿名内部类。
10.总结:
     确定接口是理想选择,因而应该总是选择接口而不是具体的类。这其实是一种诱惑。当然,对于创建类,几乎在任何时刻,都可以替代为创建一个接口和一个工厂。许多人都掉进了这种诱惑的陷阱,只要有功能就去创建接口和工厂。这种逻辑看起来好像是因为需要使用不同的具体实现,因此总是应该添加这种抽象性。这实际上已经变成了一种草率的设计优化。
 任何抽象性都应该是应真正的需求产生的。当必须时,你应该重构接口而不是到处添加额外级别的间接性,并由此带来额外的复杂性。这种额外的复杂性非常显著,如果你让某人去处理这种复杂性,只是因为你意识到由于以防万一而添加了新接口,而没有其他更具有说服力的原因,那么好吧,如果我碰上了这种事情,那么就会质疑此人所做的所有设计了。
 恰当的原则应该是优先选择类而不是接口,从来开始,如果接口的必须性变得非常明确,那么就进行重构。接口是一种重要的工具,但是它们容易被滥用。
11.部分源码:
package com.book.chap9.Interface;

import java.io.IOException;
import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;

/**
*
*使用interface的伪多重继承机制,可以让一个现有类{@link RandomDoubles}适配成为一个Scanner作用的对象
*
*<p>
*这种方式,我们可以在任何现有类之上添加新的接口,所以这意味着让方法接受接口类型,如{@link Scanner}
*是一种让任何类都可以对该方法进行适配的方式。这是使用接口而不是类的强大之处。
*</p>
*
*@author landon
*@version 1.0.0 2012-5-13 下午4:59:44
*@since JDK 1.6.0_30
*
*/

public class AdaptedRandomDoubles extends RandomDoubles implements Readable
{
   
private int count;
   
   
public AdaptedRandomDoubles(int count)
   
{
       
this.count = count;
    }

   
    @Override
   
public int read(CharBuffer cb) throws IOException
   
{
       
if(count-- == 0)
       
{
           
return -1;
        }

       
        String result = Double.toString(next()) + " ";
        cb.append(result);
       
       
return cb.length();
    }

   
   
public static void main(Stringargs)
   
{
        Scanner scanner = new Scanner(new AdaptedRandomDoubles(3));
       
       
while(scanner.hasNextDouble())
       
{
            System.out.println(scanner.nextDouble() + " ");
        }

    }


}


/**
*
* 一个要被作用于Scanner的类,用来随机产生doubles
*
* @author landon
*
*/

class RandomDoubles
{
   
private static Random random = new Random(3);
   
   
public double next()
   
{
       
return random.nextDouble();
    }

}

package com.book.chap9.Interface;
/**
*
*接口的使用
*
*灵活性,可以被依次被向上转型为每个接口
*
*@author landon
*@since JDK1.6
*@version 1.0 2012-5-7
*
*/

public class Adventure
{
   
public static void t(CanFight t)
   
{
        t.fight();
    }

   
   
public static void u(CanSwim u)
   
{
        u.swim();
    }

   
   
public static void v(CanFly v)
   
{
        v.fly();
    }

   
   
public static void w(ActionCharacter w)
   
{
        w.fight();
    }

   
   
public static void main(Stringargs)
   
{
        Hero hero = new Hero();
       
       
//被向上转型为了接口
        t(hero);
        u(hero);
        v(hero);
        w(hero);
    }

}


interface CanFight
{
   
void fight();
}


interface CanSwim
{
   
void swim();
}


interface CanFly
{
   
void fly();
}


class ActionCharacter
{
   
public void fight()
   
{
    }

}


//注: 因为Hero继承了Character类,所以默认有fight方法,所以相当于实现了CanFight接口
class Hero extends ActionCharacter implements CanFight,CanSwim,CanFly
{

    @Override
   
public void fly()
   
{
    }


    @Override
   
public void swim()
   
{
    }

}


package com.book.chap9.Interface;

import java.util.Arrays;

/**
 *
 *操作类而不是接口的方式
 *<pre>
 *创建一个能够根据所传递的对象的参数不同而具有不同行为的方法,被称为策略设计模式。这类方法包含的所要执行的算法中固定不变的部分,
 *而策略包含变化的部分,策略就是传递进去的参数对象 ,它包含要执行的代码。
 *</pre>
 *
 *1.Filter接口与Processor具有相同的接口,但是因为它不不是继承自Processor,因为filter类的创建者压根不清楚你想要将它作用于Processor,因此你
 *不能将Filter接口应用于Apply的process方法。
 *
 *2.如果我们把Processor改为一个接口呢?
 *
 *{@link NewApply}
 *
 *
 *@author landon
 *@since JDK1.6
 *@version 1.0 2012-5-3
 *
 
*/

public class Apply
{
    
public static void process(Processor processor,Object s)
    
{
        System.out.println("Using Processor: " + processor.name());
        System.out.println(processor.process(s));
    }

    
    
public static String s = "I'm tracy mcgrady";
    
    
public static void main(Stringargs)
    
{
        process(new Upcase(), s);
        process(new DownCase(), s);
        process(new Spliter(), s);
    }

}


//Processor
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 Spliter extends Processor
{
    
//注意这里是协变返回类型
    @Override
    String process(Object input)
    
{
        
//注意Arrays.toString用法
        return Arrays.toString(((String)input).split(" "));
    }

}


//*****另一组看似具有相同接口的类 *****//

//波形
class Waveform
{
    
private static long counter;
    
private static long id = counter++;
    
    @Override
    
public String toString()
    
{
        
return "Waveform " + id;
    }

}


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

    
    Waveform process(Waveform input)
    
{
        
return input;
    }

}


//LowPass
class LowPass extends Filter
{
    
private double cutoff;
    
    
public LowPass(double cutoff)
    
{
        
this.cutoff = cutoff;
    }

    
    
//这里处理没有发生变化 dummy
    @Override
    Waveform process(Waveform input)
    
{
        
return input;
    }

}


//HighPass
class HighPass extends Filter
{
    
private double cutoff;
    
    
public HighPass(double cutoff)
    
{
        
this.cutoff = cutoff;
    }

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

}


//BandPass
class BandPass extends Filter
{
    
private double lowCutoff;
    
private double hightCutoff;
    
    
public BandPass(double lc,double hc)
    
{
        lowCutoff = lc;
        hightCutoff = hc;
    }

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

}


package com.book.chap9.Interface;
/**
*
*组合接口的名字冲突,请尽量避免在打算组合的不同接口中使用相同的方法名
*
*@author landon
*@since JDK1.6
*@version 1.0 2012-5-7
*
*/

public class CombineInterfaceCollision
{
}



//void f
interface I1
{
   
void f();
}


//int f(int)
interface I2
{
   
int f(int i);
}


//int f()
interface I3
{
   
int f();
}


//int  f()
class C
{
   
public int f()
   
{
       
return 1;
    }

}


//实现了两个接口
class C2 implements I1,I2
{

    @Override
   
public int f(int i)
   
{
       
return 1;
    }


    @Override
   
public void f()//重载f
    {
    }

}



class C3 extends C implements I2
{
    @Override
   
public int f(int i)//重载f
    {
       
return 1;
    }

}


class C4 extends C implements I3
{
}


//下面是编译报错的

//方法名只能是因为方法只是返回值不同而已
//The return types are incompatible for the inherited methods I1.f(), C.f()
/*class C5 extends C implements I1
{
   
}*/


/*interface I4 extends I1,I3
{
    
}*/

package com.book.chap9.Interface;
/**
 *
 *接口与工厂
 *
 *工厂方法
 *
 *@author landon
 *@since JDK1.6
 *@version 1.0 2012-5-15
 *
 
*/

public class Factories
{
    
//方法参数为一个工厂服务接口
    public static void serviceConsumer(ServiceFactory factory)
    
{
        Service service = factory.getService();
        service.method1();
        service.method2();
    }

    
    
public static void main(Stringargs)
    
{
        
//传服务工厂1
        serviceConsumer(new Implementation1Factory());
        
//动态灵活的更改为服务工厂2
        serviceConsumer(new Implementation2Factory());
    }

}


//接口服务
interface Service
{
    
void method1();
    
void method2();
}


//接口服务工厂
interface ServiceFactory
{
    
//获取服务
    Service getService();
}


//服务实现1
class Implementation1 implements Service
{

    @Override
    
public void method1()
    
{
        System.out.println("Implementation1 method1");
    }


    @Override
    
public void method2()
    
{
        System.out.println("Implementation1 method2");
    }

}


//服务实现1工厂
class Implementation1Factory implements ServiceFactory
{

    @Override
    
public Service getService()
    
{
        
return new Implementation1(); 
    }

}


//服务实现2
class Implementation2 implements Service
{

    @Override
    
public void method1()
    
{
        System.out.println("Implementation2 method1");
    }


    @Override
    
public void method2()
    
{
        System.out.println("Implementation2 method2");
    }

}


//服务实现2工厂
class Implementation2Factory implements ServiceFactory
{

    @Override
    
public Service getService()
    
{
        
return new Implementation2(); 
    }

}


package com.book.chap9.Interface;
/**
*
*如果不是用工厂方法,你的代码就必须在某处指定将要创建的Service确切类型,以便调用合适的构造器。
*为什么我们想要添加这种额外级别的间接性呢?一个常见的原因是想要创建框架:假设你正在创建一个对弈游戏系统,
*例如,在相同的棋盘上下国际象棋和西洋跳棋,如果Games类,处理逻辑,表示一段复杂的代码,那么这种方式允许你在不同类型的游戏中复用这段代码{@link Games}
*
*@author landon
*@since JDK1.6
*@version 1.0 2012-5-15
*
*/

public class Games
{
   
//玩游戏
    public static void playGame(GameFactory factory)
   
{
        Game game = factory.getGame();
       
       
while(game.move())
       
{
           
//.做其他操作
        }

    }

   
   
//运行游戏,游戏的双方各自操作
    public static void main(Stringargs)
   
{
        playGame(new CheckersFactory());
        playGame(new ChessFactory());
    }

}


interface Game
{
   
boolean move();
}


interface GameFactory
{
    Game getGame();
}


//国际象棋的一方
class Checkers implements Game
{
   
private int moves = 0;
   
private static final int MOVES = 3;
    @Override
   
public boolean move()
   
{
        System.out.println("Checkers move: " + moves);
       
       
return ++moves != MOVES;
    }

}


//CheckersFactory
class CheckersFactory implements GameFactory
{
    @Override
   
public Game getGame()
   
{
       
return new Checkers();
    }

}


//国际象棋的另一方
class Chess implements Game
{
   
private int moves = 0;
   
private static final int MOVES = 4;
   
    @Override
   
public boolean move()
   
{
        System.out.println("Chess move: " + moves);
       
       
return ++moves != MOVES;
    }

}


//ChessFactory
class ChessFactory implements GameFactory
{
    @Override
   
public Game getGame()
   
{
       
return new Chess();
    }

}


package com.book.chap9.Interface;
/**
*
*通过继承来扩展接口
*
*Vampire用到的语法仅适用于接口继承,一般情况下,只可将extends用于单一类,但是可以
*引用多个基类接口
*
*@author landon
*@since JDK1.6
*@version 1.0 2012-5-7
*
*/

public class HorrorShow
{
   
static void u(Monster m)
   
{
        m.menace();
    }

   
   
static void v(DangerousMonster m)
   
{
        m.menace();
        m.destroy();
    }

   
   
static void w(Lethal l)
   
{
        l.kill();
    }

   
   
public static void main(Stringargs)
   
{
        DangerousMonster tracy = new DragonZilla();
        u(tracy);
        v(tracy);
       
        Vampire landon = new VeryBadVampire();
        u(landon);
        v(landon);
        w(landon);
    }

}


interface Monster
{
   
void menace();
}


//接口继承
interface DangerousMonster extends Monster
{
   
void destroy();
}


interface Lethal
{
   
void kill();
}


//
class DragonZilla implements DangerousMonster
{

    @Override
   
public void menace()
   
{
    }


    @Override
   
public void destroy()
   
{
    }

   
}


//吸血蝙蝠,继承了一个已经继承的接口DangerousMonster
interface Vampire extends DangerousMonster,Lethal
{
   
void drinkBlood();
}


class VeryBadVampire implements Vampire
{

    @Override
   
public void destroy()
   
{
    }


    @Override
   
public void menace()
   
{
    }


    @Override
   
public void kill()
   
{
    }


    @Override
   
public void drinkBlood()
   
{
    }

   
}

package com.book.chap9.Interface;
/**
*
*在Java SE5之前,通常使用接口来定义常量群组
*默认都是static和final的
*
*@author landon
*@version 1.0.0 2012-5-13 下午5:39:13
*@since JDK 1.6.0_30
*
*/

public interface Months
{
   
int JANUARY = 1;
   
int FEBRUARY = 2;
   
int MARCH = 3;
   
int APRIL = 4;
   
int MAY = 5;
   
int JUNE = 6;
   
int JULY = 7;
   
int AUGUST = 8;
   
int SEPTEMBER = 9;
   
int OCTORBER = 10;
   
int NOVEMBER = 11;
   
int DECEMBER = 12;
}

package com.book.chap9.Interface;

import java.util.Arrays;

/**
*
*使用接口处理耦合的情况
*
*1.复用代码的第一种方式是使客户端程序员遵循该接口来编写他们自己的类,如StringProcessor,NewUpcase,NewSpliter,因为之前的接口变成了ProcessorInterface
*2.但是你经常碰到的情况是你无法修改你想要使用的类,{@link Filter}等波形例子是被发现而并非创建的。在这些情况下,可以使用适配器模式,适配器代码将接受你所
*拥有的接口,并产生你所需要的接口。{@link FilterAdapter}
*
*{@link Apply}
*
*@author landon
*@since JDK1.6
*@version 1.0 2012-5-3
*
*/

public class NewApply
{
   
public static void process(ProcessorInterface processor,Object s)
   
{
        System.out.println("Using Processor: " + processor.name());
        System.out.println(processor.process(s));
    }

   
   
public static void main(Stringargs)
   
{
       
//直接修改,重新使用接口编写的类
        NewApply.process(new NewUpcase(), StringProcessor.s);
        NewApply.process(new NewDownCase(), StringProcessor.s);
        NewApply.process(new NewSpliter(), StringProcessor.s);
       
       
//使用适配器修改的类
        Waveform waveform = new Waveform();
        NewApply.process(new FilterAdapter(new LowPass(1.0)), waveform);
        NewApply.process(new FilterAdapter(new HighPass(1.0)), waveform);
        NewApply.process(new FilterAdapter(new BandPass(1.0,2.0)), waveform);
    }

}


//Processor
interface ProcessorInterface
{
   
public String name();
   
    Object process(Object input);
}


//抽象的字符串处理器
abstract class StringProcessor implements ProcessorInterface
{
    @Override
   
public String name()
   
{
       
return getClass().getSimpleName();
    }

   
   
//协变返回类型
    @Override
   
public abstract String process(Object input);
   
   
public static String s = "I'm tracy mcgrady";
}


//大写字符串处理器
class NewUpcase extends StringProcessor
{
   
//注意这里一定要加上public,否则编译报错,因为接口的方法默认都是public的,继承过程中不能降低可访问性
    @Override
   
public String process(Object input)
   
{
       
return ((String)input).toUpperCase();
    }

}


//小写处理器
class NewDownCase extends StringProcessor
{
    @Override
   
public String process(Object input)
   
{
       
return ((String)input).toLowerCase();
    }

}


//字符串切分处理器
class NewSpliter extends StringProcessor
{
    @Override
   
public String process(Object input)
   
{
       
//注意Arrays.toString用法
        return Arrays.toString(((String)input).split(" "));
    }

}


//****** 使用适配器来改变之前波形的例子 ******//

//适配器,生成了具有ProcessorInterface的对象
class FilterAdapter implements ProcessorInterface
{
   
//这是自己拥有的接口
    Filter filter;
   
   
public FilterAdapter(Filter filter)
   
{
       
this.filter = filter;
    }

   
   
//而且这个例子明显用到了代理,即全部用传入的参数filter实现所有的覆盖的方法
    @Override
   
public String name()
   
{
       
return filter.name();
    }


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

   
}


package com.book.chap9.Interface;

import java.io.IOException;
import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;

/**
*
*随机取词
*<p>测试使用接口的灵活性,策略设计模式</p>
*<p>本例是实现了Readable接口,使之可以作用于Scanner</p>
*
*<pre>
*Readable接口只要求实现read方法,在read内部,将输入内容添加到CharBuffer参数中
*</pre>
*
*@author landon
*@since JDK1.6
*@version 1.0 2012-5-9
*
*/

public class RandomWords implements Readable
{
   
public static Random random = new Random(3);
   
//大写字母数组
    private static final char[] capitals = "ABCDEFGHIJKLMNOPQRSZUVWXYZ ".toCharArray();
   
//小写字母数组
    private static final char[] lowers = "abcdefghijklmnopqrstuvwxyz".toCharArray();
   
//元音
    private static final char[] vowels = "aeiou".toCharArray();
   
//读取的次数
    private int count;
   
   
public RandomWords(int count)
   
{
       
this.count = count;
    }

   
    @Override
   
public int read(CharBuffer cb) throws IOException
   
{
       
if(count-- == 0)
       
{
           
return -1;//读取结束标志
        }

       
        cb.append(capitals[random.nextInt(capitals.length)]);
//nextInt包括0不过不包括指定值n
        for(int i = 0;i < 4;i++)
       
{
            cb.append(lowers[random.nextInt(lowers.length)]);
            cb.append(vowels[random.nextInt(vowels.length)]);
        }

       
        cb.append(
" ");
       
       
return 10;//10为CharBuffer追加的字符数目
    }

   
   
public static void main(Stringargs)
   
{
        Scanner s
= new Scanner(new RandomWords(10));
       
while(s.hasNext())
       
{
            System.out.println(s.next());
        }

    }

}



package com.book.chap9.Interface;

import java.util.Random;
import static java.lang.System.out;

/**
*
*测试接口中域的初始化
*
*
@author landon
*
@version 1.0.0 2012-5-13 下午5:57:24
*
@since JDK 1.6.0_30
*
*/

public class TestRandVals
{
   
public static void main(Stringargs)
   
{
        out.println(RandVals.RANDOM_INT);
out.println(RandVals.RANDOM_LONG);
        out.println(RandVals.RANDOM_DOUBLE);
        out.println(RandVals.RANDOM_FLOAT);
       
        out.println(RandVals.RANDOM_INT);
        out.println(RandVals.RANDOM_LONG);
        out.println(RandVals.RANDOM_DOUBLE);
        out.println(RandVals.RANDOM_FLOAT);
    }

}


interface RandVals
{
    Random random
= new Random(3);
   
   
int RANDOM_INT = random.nextInt();
   
long RANDOM_LONG = random.nextLong();
   
float RANDOM_FLOAT = random.nextFloat();
   
double RANDOM_DOUBLE = random.nextDouble();
}

posted on 2013-01-08 18:50 landon 阅读(1858) 评论(1)  编辑  收藏 所属分类: ProgramBook

FeedBack:
# re: Thinking in Java 4th chap9笔记
2013-01-08 20:54 | 将夜
要一项一项认真学才行。  回复  更多评论
  

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


网站导航: