Java进阶之路_重温《java编程思想》篇(五)

1.接口:

适配器模式:以前看大话设计模式的时候也接触过适配器模式,当时感觉只是停留在表面的理解上,今天看了接口这一章,在具体的场景中提出来的,感觉确实不一样。首先把代码拿上来吧:

package mindview;

public class AdapterPattern {

	public static void main(String[] args) {

		String str = "abcdef";
		TransferString ts = new TransferString();
		String result = AdapterPattern.process(new TransferAdapter(ts), str);
		System.out.println(result);
	}
	public static String process(Processer p, String str){
		return p.process(str);
	} 
}
interface Processer{
	public String process(String str);
}

class TransferAdapter implements Processer{

	Transfer transfer;
	public TransferAdapter(Transfer transfer) {
		this.transfer = transfer;
	}
	@Override
	public String process(String str) {
		return transfer.process(str);
	}
	
}

class Transfer{
	public String process(String str){return null;}
}

class TransferString extends Transfer{
	public String process(String str){
		
		char[] chs = str.toCharArray();
		for(int i = 0; i < chs.length && i+1 < chs.length; i += 2){
			char tmp = chs[i];
			chs[i] = chs[i+1];
			chs[i+1] = tmp;
		}
		return new String(chs);
	}
}

这个程序是第9章的练习题11,请忽略将字符串中每一对字符进行交换的算法,不知道是不是对的,理解能力和算法能力都有待提高~~我们这边只是看一下程序的整体结构,在主类AdapterPattern中有一个process方法,里面有两个参数,一个是Processer接口类型 ,一个是需要被转换的字符串,这样,这个process方法就只能处理从Processer接口继承下来的类了,现在我们新加了一个Transfer系列的类,它就无法处理;因此,我们就添加了一个同样实现了Processer接口的TransferAdapter类来适配Transfer系列的类,这样就可以把Transfer转换为Processer了。

使用接口的核心原因:为了能够向上转型为多个基类型(以及由此而来的灵活性)。

接口使用的经典案例:工厂方法设计模式:实例(第九章练习题18)

package mindview;

public class FactoryPattern {

	public static void main(String[] args) {

		useCycle(new UnicycleFactory());
		useCycle(new BicycleFactory());
		useCycle(new TricycleFactory());
		
	}
	public static void useCycle(CycleFactory factory){
		factory.getCycle().move();
	}

}

interface Cycle{
	public void move();
}
class Unicycle implements Cycle{

	@Override
	public void move() {

		System.out.println("Unicycle move.");
	}
	
}
class Bicycle implements Cycle{

	@Override
	public void move() {

		System.out.println("Bicycle move.");
	}
	
}
class Tricycle implements Cycle{

	@Override
	public void move() {

		System.out.println("Tricycle move.");
	}
	
}

interface CycleFactory{
	Cycle getCycle();
}
class UnicycleFactory implements CycleFactory{

	@Override
	public Cycle getCycle() {
		return new Unicycle();
	}
	
}
class BicycleFactory implements CycleFactory{

	@Override
	public Cycle getCycle() {
		return new Bicycle();
	}
	
}
class TricycleFactory implements CycleFactory{

	@Override
	public Cycle getCycle() {
		return new Tricycle();
	}
	
}


匿名内部类版本的工厂方法:

package com.mindview.test;

public class Factories {

	public static void main(String[] args) {
		serviceConsumer(Implementation1.factory);
		serviceConsumer(Implementation2.factory);
	}/**OutPut:
	Implementation1.method1()
	Implementation1.method2()
	Implementation2.method1()
	Implementation2.method2()
	*///~
	public static void serviceConsumer(ServiceFactory fact){
		Service service = fact.getService();
		service.method1();
		service.method2();
	}
}
interface Service{
	void method1();
	void method2();
}
interface ServiceFactory{
	Service getService();
}
class Implementation1 implements Service{

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

	@Override
	public void method2() {
		System.out.println("Implementation1.method2()");
	}
	public static ServiceFactory factory = new ServiceFactory() {
		@Override
		public Service getService() {
			return new Implementation1();
		}
	};
}
class Implementation2 implements Service{

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

	@Override
	public void method2() {
		System.out.println("Implementation2.method2()");
	}
	public static ServiceFactory factory = new ServiceFactory() {
		@Override
		public Service getService() {
			return new Implementation2();
		}
	};
}


闭包与回调:

闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域,通过这个定义可以看出内部类是面向对象的闭包,因为他不仅包含外围类的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内。内部类有权操作所有的成员,包括private成员。

通过JavaScript代码比较容易理解:一个外部的函数里面声明了一个内部的函数,内部函数可以访问外部函数中的局部变量、传入的参数和其他内部函数,当这个内部函数可以被外部函数之外的地方引用时,就形成了一个闭包。这个时候,即便外部函数已经执行完成,该内部函数仍然可以被执行,并且其中所用到的函数的局部变量、传入的参数等仍然保留外部函数执行结束时的值,代码示例如下:

function Outer(){  
    var i=0;  
    function Inner(){  
        alert(++i);  
    }  
    return Inner;  
}  
var inner = Outer();  
inner();  


JavaScript的闭包是面向函数的,而java的闭包则是面向对象的,Java是通过内部类来实现闭包的,因为内部类可以访问到外围类的的所有成员,包括private的成员,因此在外围类中提供一个内部类的应用给外面的类或方法,这样就是一个闭包了,代码如下:

package mindview.closure;

public class Callbacks {

	public static void main(String[] args) {
		Callee1 c1 = new Callee1();
		Callee2 c2 = new Callee2();
		MyIncrement.f(c2);
		Caller caller1 = new Caller(c1);
		Caller caller2 = new Caller(c2.getCallbackReference());
		caller1.go();
		caller1.go();
		caller2.go();
		caller2.go();
	}
}/**Output:
Other operation
1
1
2
Other operation
2
Other operation
3
*/
interface Incrementable{
	void increment();
}
class Callee1 implements Incrementable{

	private int i = 0;
	@Override
	public void increment() {
		i++;
		System.out.println(i);
	}
}
class MyIncrement{
	public void increment(){
		System.out.println("Other operation");
	}
	static void f(MyIncrement mi){
		mi.increment();
	}
}
class Callee2 extends MyIncrement{
	private int i = 0;
	public void increment(){
		super.increment();
		i++;
		System.out.println(i);
	}
	private class Closure implements Incrementable{
		@Override
		public void increment() {
			Callee2.this.increment();
		}
	}
	Incrementable getCallbackReference(){
		return new Closure();
	}
}
class Caller{
	private Incrementable callbackReference;
	Caller(Incrementable cbh){
		callbackReference = cbh;
	}
	void go(){
		callbackReference.increment();
	}
}

通过内部类提供闭包的功能是优良的解决方案,它比指针更灵活、更安全。

编程上来说,一般使用一个库或类时,是你主动调用人家的API,这个叫Call,有的时候这样不能满足需要,需要你注册(注入)你自己的程序(比如一个对象),然后让人家在合适的时候来调用你,这叫Callback。设计模式中的Observer就是例子:所有的观察者都需要向自己关心的主题Observable注册,然后主题在适当时机(主题类对象的属性发生变化时)通知所有订阅它的观察者并更新,其中观察者都实现了一个统一的Observer接口中的Update方法。

回调实质上是指一个类尽管实际上实现了某种功能,但是没有直接提供相应的接口,客户类可以通过这个类的内部类的接口来获得这种功能。而这个内部类本身并没有提供真正的实现,仅仅调用外部类的实现。可见,回调充分发挥了内部类所具有的访问外部类的实现细节的优势。

上面代码中Caller类中的go方法就是对callbackReference中increment()方法的一个回调。






你可能感兴趣的:(Java进阶之路_重温《java编程思想》篇(五))