概念
定义一个用于常见对象的接口,让子类决定实例化哪个类.工厂方法使一个类的实例化延迟到其子类.
举个栗子
以学习雷锋为栗
先来看看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{}
定义一个接口,用来创建具体类
public interface IFactory {
LeiFeng Create();//依赖抽象不依赖细节.
}
两个志愿者各自的工厂类,都实现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();
//延时到子类创建对象
LeiFeng leiFeng = factory.Create();
leiFeng.buyrice();
leiFeng.wash();
leiFeng.sweep();
Android中的工厂方法模式
以Activity
为栗
当Activity
注入xml
文件时,加载view
的过程,就是通过工厂方法模式来加载的.
注入xml文件时,使用setContentView(int)
方法,我们去Activity
中找到这个方法,
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
我们发现他是调用window
的setContentView(int)
方法,我们找到这个getWindow()
方法,发现他返回的是一个Window
对象,但是这个对象是个抽象类,我们找到这个抽象类的具体实现是一个PhoneWindow
对象.我们可以在attach(...)
方法中找到这个类的初始化.
mWindow = new PhoneWindow(this, window);
继续跟进,找到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);
}
}
我们发现了mLayoutInflater.inflate(layoutResID, mContentParent);
这句代码,是不是很熟悉,ListView中经常使用,只是少了个参数,继续跟进,发现它最终还是调用了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(...)
方法,毫无疑问,它是通过这个方法来创建view的,继续跟进,我们能在其中发现以下代码
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;
}
...
}
是不是看着很熟悉,我们去看看这个mFactory
和mFactory2
是个什么东西?
最终发现,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);
}
我们不需要去查看这个接口具体的实现,但是到现在过程已经很清晰了
总结:我们在Activity
中注入xml
文件,之后内部去解析xml
文件,最后在LayoutInflate中
通过Factory
接口具体去实例化.
对照定义,我们发现,Factory
是常见对象的接口,LayoutInflate
是子类(决定具体实例化哪个View
),而Activity
就是工厂.
看下UML图巩固一下
结语
有错请指出.
学无止境.