概念
定義一個用于常見對象的接口,讓子類決定實例化哪個類.工廠方法使一個類的實例化延遲到其子類.
舉個栗子
以學(xué)習(xí)雷鋒為栗
先來看看UML圖.
首先定義一個雷鋒類
public class LeiFeng {
public void wash() {
System.out.println("wash");
}
public void sweep() {
System.out.println("sweep");
}
public void buyrice() {
System.out.println("buyrice");
}
}
定義兩個志愿者類,繼承雷鋒
public class Undergraduate extends LeiFeng {}
public class Volunteer extends LeiFeng{}
定義一個接口,用來創(chuàng)建具體類
public interface IFactory {
LeiFeng Create();//依賴抽象不依賴細節(jié).
}
兩個志愿者各自的工廠類,都實現(xiàn)IFacory接口
public class UndergraduateFactory implements IFactory {
@Override
public LeiFeng Create() {
return new Undergraduate();
}
}
public class VolunteerFactory implements IFactory {
@Override
public LeiFeng Create() {
return new Volunteer();
}
}
使用:
//可以改為new VolunteerFactory();
IFactory factory = new UndergraduateFactory();
//延時到子類創(chuàng)建對象
LeiFeng leiFeng = factory.Create();
leiFeng.buyrice();
leiFeng.wash();
leiFeng.sweep();
Android中的工廠方法模式
以Activity
為栗
當(dāng)Activity
注入xml
文件時,加載view
的過程,就是通過工廠方法模式來加載的.
注入xml文件時,使用setContentView(int)
方法,我們?nèi)?code>Activity中找到這個方法,
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
我們發(fā)現(xiàn)他是調(diào)用window
的setContentView(int)
方法,我們找到這個getWindow()
方法,發(fā)現(xiàn)他返回的是一個Window
對象,但是這個對象是個抽象類,我們找到這個抽象類的具體實現(xiàn)是一個PhoneWindow
對象.我們可以在attach(...)
方法中找到這個類的初始化.
mWindow = new PhoneWindow(this, window);
繼續(xù)跟進,找到PhoneWindow
的setContentView(int)
方法
public void setContentView(int layoutResID) {
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
}
我們發(fā)現(xiàn)了mLayoutInflater.inflate(layoutResID, mContentParent);
這句代碼,是不是很熟悉,ListView中經(jīng)常使用,只是少了個參數(shù),繼續(xù)跟進,發(fā)現(xiàn)它最終還是調(diào)用了LayoutInflate類中的
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
// Temp is the root view that was found in the xml
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
}
我們在方法中找到createViewFromTag(...)
方法,毫無疑問,它是通過這個方法來創(chuàng)建view的,繼續(xù)跟進,我們能在其中發(fā)現(xiàn)以下代碼
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
boolean ignoreThemeAttr) {
...
View view;
if (mFactory2 != null) {
view = mFactory2.onCreateView(parent, name, context, attrs);
} else if (mFactory != null) {
view = mFactory.onCreateView(name, context, attrs);
} else {
view = null;
}
...
}
是不是看著很熟悉,我們?nèi)タ纯催@個mFactory
和mFactory2
是個什么東西?
最終發(fā)現(xiàn),mFactory
是一個Factory
接口,mFactory2
是一個Factory2
接口,這個接口繼承自mFactory.
public interface Factory {
public View onCreateView(String name, Context context, AttributeSet attrs);
}
public interface Factory2 extends Factory {
public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
}
我們不需要去查看這個接口具體的實現(xiàn),但是到現(xiàn)在過程已經(jīng)很清晰了
總結(jié):我們在Activity
中注入xml
文件,之后內(nèi)部去解析xml
文件,最后在LayoutInflate中
通過Factory
接口具體去實例化.
對照定義,我們發(fā)現(xiàn),Factory
是常見對象的接口,LayoutInflate
是子類(決定具體實例化哪個View
),而Activity
就是工廠.
看下UML圖鞏固一下
結(jié)語
有錯請指出.
學(xué)無止境.