Framework中的钩子函数

首先了解下钩子函数:

钩子是一种被声明在抽象类中的方法,但只有空的或默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。
比如:

声明有钩子的抽象类:

package com.dlo.designpatterns.hook;

import android.util.Log;

public abstract class CaffeineBeverageWithHook {
	String TAG = "CaffeineBeverageWithHook";
	public final void prepareRecipe() {
		boilWater();
		brew();
		pourInCup();
		if (customerWantsCondiments()) {
			addCondiments();
		}
	}

	abstract void brew();

	abstract void addCondiments();

	void boilWater() {
		Log.d(TAG,"Boiling water");
	}

	void pourInCup() {
		Log.d(TAG,"pouring into cup");
	}

	boolean customerWantsCondiments() {
		Log.d(TAG,"customerWantsCondiments");
		return true;
	}
}

实现钩子的具体派生类1:

package com.dlo.designpatterns.hook;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import android.util.Log;

public class CoffeeWithHook extends CaffeineBeverageWithHook {
	String TAG = "CoffeeWithHook";
	@Override
	void brew() {
		// TODO Auto-generated method stub
		Log.d(TAG,"Adding Sugar and Milk");
	}

	@Override
	void addCondiments() {
		// TODO Auto-generated method stub
		Log.d(TAG,"addCondiments");
	}

	public boolean customerWantsCondiments() {
		String answer = getUserInput();
		if (answer.toLowerCase().startsWith("y")) {
			return true;
		} else {
			return false;
		}
	}

	private String getUserInput() {
		String answer = null;
		Log.d(TAG,"Would you like milk and sugar with your coffee(y/n)?");
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		try {
			answer = in.readLine();
		} catch (IOException ioe) {
			System.err.println("IO error trying to read your answer");
		}

		if (answer == null) {
			return "no";
		}
		return answer;
	}
}
实现钩子的具体派生类2:

package com.dlo.designpatterns.hook;

import android.util.Log;

public class TeaWithHook extends CaffeineBeverageWithHook {
	String TAG = "TeaWithHook";
	@Override
	void brew() {
		// TODO Auto-generated method stub
		Log.d(TAG,"brew");
	}

	@Override
	void addCondiments() {
		// TODO Auto-generated method stub
		Log.d(TAG,"addCondiments");
	}

}
测试类,分别测试类1和类2的行为:

package com.dlo.designpatterns;

import com.dlo.designpatterns.hook.CoffeeWithHook;
import com.dlo.designpatterns.hook.TeaWithHook;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {
	String TAG = "MainActivity";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		TeaWithHook teaHook = new TeaWithHook();
	     CoffeeWithHook coffeeHook = new CoffeeWithHook();
	     
	     Log.d(TAG,"\nMaking tea...");
	     teaHook.prepareRecipe();
	     
	     Log.d(TAG,"\n Making coffee...");
	     coffeeHook.prepareRecipe();
	}
}

我 们在prepareRecipe函数中加入条件语句,当用户需要调料的时候,才调用addCondiments(),addCondiments()只返 回true,不做别的事,这就是一个钩子,子类可以覆盖这个方法,但不一定非得这么做。这样在子类中,钩子控制了咖啡因饮料是否执行某部分算法(是否加调 料)。

钩子和抽象方法的使用场景:

当子类必须提供算法中某个方法或步骤的实现时,就使用抽象方法。如果这个部分是可选的,就用钩子。如果是钩子的话,子类可以选择实现这个钩子,但并不强制这么做。
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Android框架层中对钩子的实际应用举例:
//AdapterView.java中

public abstract class AdapterView<T extends Adapter> extends ViewGroup {
	
	/**
     * @return The view corresponding to the currently selected item, or null
     * if nothing is selected
     */
	public abstract View getSelectedView();
	
	private void fireOnSelected() {
        if (mOnItemSelectedListener == null) {
            return;
        }
        final int selection = getSelectedItemPosition();
        if (selection >= 0) {
            View v = getSelectedView();
            mOnItemSelectedListener.onItemSelected(this, v, selection,
                    getAdapter().getItemId(selection));
        } else {
            mOnItemSelectedListener.onNothingSelected(this);
        }
    }
}


这里就使用了钩子函数getSelectedView();具体实现交给子类,而可以在AdapterView的fireOnSelected等函数中作算法控制。
比如在子类AbsListView中就有了实现:
//AbsListView.java

public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
        ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
        ViewTreeObserver.OnTouchModeChangeListener,
        RemoteViewsAdapter.RemoteAdapterConnectionCallback {
 @Override
    @ViewDebug.ExportedProperty
    public View getSelectedView() {
        if (mItemCount > 0 && mSelectedPosition >= 0) {
            return getChildAt(mSelectedPosition - mFirstPosition);
        } else {
            return null;
        }
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值