今天试着将公司的一大堆的android View.OnClickListener条件调度程序重构为Command模式,经测试,程序没有出错,代码的可读性高了,而且消除了不少重复代码,先将原始代码和重构后的代码贴至如下:
1.原先代码:
private void pull_to_refresh() {
NavigationTextView textView;
for (int i = 0; i < inforTitles.size(); i++) {
textView = inforTitles.get(i);
if (textView.isSelected()) {
setViewBg(textView);
/*
* if(footerViewIsVisible){ footLayout.setVisibility(View.GONE);
* footerViewIsVisible=false; }
*/
inforAdapter.updateInforList(textView.getTitleUrl(), i, true);
listView.setSelection(0);
break;
}
}
}
private View.OnClickListener listener = new View.OnClickListener() {
public void onClick(View v) {
int viewId = v.getId();
if (viewId == R.id.information_menu_child_refresh) {
NavigationTextView textView;
for (int i = 0; i < inforTitles.size(); i++) {
textView = inforTitles.get(i);
if (textView.isSelected()) {
setViewBg(textView);
if (footerViewIsVisible) {
footLayout.setVisibility(View.GONE);
footerViewIsVisible = false;
}
listView.showProgressBar();
inforAdapter.updateInforList(textView.getTitleUrl(), i,
true);
listView.setSelection(0);
break;
}
}
} else if (viewId == R.id.information_menu_child_offine_download) {
down();
} else if (viewId == R.id.information_menu_child_custom_channel) {
Intent cusIntent = new Intent();
cusIntent.setClass(InformationBrowserActivity.this,
CustomChannelActivity.class);
Bundle b = new Bundle();
int backFlag;
if (moreNaviListLayout.getVisibility() == View.VISIBLE) {
backFlag = Config.NAVI_MORE;
} else {
backFlag = Config.NAVI_FIRST;
}
b.putInt("backFlag", backFlag);
cusIntent.putExtras(b);
startActivity(cusIntent);
layout.removeAllViews();
} else if (viewId == R.id.information_menu_child_favorite) {
Intent favoriteIntent = new Intent(
InformationBrowserActivity.this,
MoreFavoriteActivity.class);
startActivity(favoriteIntent);
} else if (viewId == R.id.information_menu_child_setting) {
Intent settingIntent = new Intent(
InformationBrowserActivity.this, PconlineSetting.class);
startActivity(settingIntent);
}/*
* else if (viewId == R.id.information_menu_child_select_city) {
* changeCity(); }
*/else if (viewId == R.id.information_menu_child_search) {
Intent searchIntent = new Intent(
InformationBrowserActivity.this,
InformationCategorySearchResultActivity.class);
startActivity(searchIntent);
} /*
* else if (viewId == R.id.information_menu_child_exit) {
* onBackPressed(); }
*/else if (viewId == R.id.information_menu_top_layout) {
mPopupWindow.dismiss();
}
mPopupWindow.dismiss();
}
};
重构后的代码:
private void pull_to_refresh() {
boolean isHanlderForFooterViewInVisible = false;
refresh(isHanlderForFooterViewInVisible);
}
private void setInInVisibleForFooterViews(boolean isVisible) {
if (isVisible) {
if (footerViewIsVisible) {
footLayout.setVisibility(View.GONE);
footerViewIsVisible = false;
}
listView.showProgressBar();
}
}
private void refresh(boolean isHanlderForFooterViewInVisible) {
NavigationTextView textView;
for (int i = 0; i < inforTitles.size(); i++) {
textView = inforTitles.get(i);
if (textView.isSelected()) {
setViewBg(textView);
setInInVisibleForFooterViews(isHanlderForFooterViewInVisible);
inforAdapter.updateInforList(textView.getTitleUrl(), i, true);
listView.setSelection(0);
break;
}
}
}
private Map<Integer, MenuChildListenerResponse> maps = new HashMap<Integer, MenuChildListenerResponse>();
private void compositeCommandForMenuChildListener() {
maps.put(R.id.information_menu_child_refresh, new MenuChildRefresh());
maps.put(R.id.information_menu_child_offine_download,
new MenuChildOfflineDownload());
maps.put(R.id.information_menu_child_custom_channel,
new MenuChildCustomChannel());
maps.put(R.id.information_menu_child_favorite, new MenuChildFavorite());
maps.put(R.id.information_menu_child_setting, new MenuChildSetting());
maps.put(R.id.information_menu_child_search, new MenuChildSearch());
maps.put(R.id.information_menu_top_layout, new MenuTopLayout());
}
private abstract class MenuChildListenerResponse {
abstract void execute();
void composeIntent(Class<?> c, Bundle b) {
Intent newIntent = new Intent(InformationBrowserActivity.this, c);
if (b != null)
newIntent.putExtras(b);
startActivity(newIntent);
}
}
private class MenuChildRefresh extends MenuChildListenerResponse {
public void execute() {
boolean isHanlderForFooterViewInVisible = true;
refresh(isHanlderForFooterViewInVisible);
}
}
private class MenuChildOfflineDownload extends MenuChildListenerResponse {
@Override
void execute() {
down();
}
}
private class MenuChildCustomChannel extends MenuChildListenerResponse {
void execute() {
Bundle b = new Bundle();
int backFlag;
if (moreNaviListLayout.getVisibility() == View.VISIBLE) {
backFlag = Config.NAVI_MORE;
} else {
backFlag = Config.NAVI_FIRST;
}
b.putInt("backFlag", backFlag);
composeIntent(CustomChannelActivity.class, b);
layout.removeAllViews();
}
}
private class MenuChildFavorite extends MenuChildListenerResponse {
void execute() {
composeIntent(MoreFavoriteActivity.class, null);
}
}
private class MenuChildSetting extends MenuChildListenerResponse {
void execute() {
composeIntent(PconlineSetting.class, null);
}
}
private class MenuChildSearch extends MenuChildListenerResponse {
void execute() {
composeIntent(InformationCategorySearchResultActivity.class, null);
}
}
private class MenuTopLayout extends MenuChildListenerResponse {
void execute() {
mPopupWindow.dismiss();
}
}
private View.OnClickListener listener = new View.OnClickListener() {
public void onClick(View v) {
int viewId = v.getId();
maps.get(viewId).execute();
new MenuTopLayout().execute();
}
};
最大的子程序行数也没超过10行,可读性是不是好了很多呢?而且当再次添加菜单的View和View的OnClickListener事件时,只要继承与MenuChildListenerResponse并覆盖execute方法,然后在Map对象注册该View的id和具体的命令对象即可,不会影响到其他View的处理逻辑,符合了二进制兼容性原则。若发现有重复代码,可用Pull Up重构,将重复代码移到超类。 当然将条件调度程序或者Switch-case程序重构为Command模式的前提是这些程序条件判断比较复杂,比如一屏不能显示完所有的if-else,switch-case,否则,这样重构后只会增加了代码的复杂性。
继续加油,将设计模式用在重构上!