工厂方法模式之Activity创建View

概念

定义一个用于常见对象的接口,让子类决定实例化哪个类.工厂方法使一个类的实例化延迟到其子类.

举个栗子

以学习雷锋为栗

先来看看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();
}

我们发现他是调用windowsetContentView(int)方法,我们找到这个getWindow()方法,发现他返回的是一个Window对象,但是这个对象是个抽象类,我们找到这个抽象类的具体实现是一个PhoneWindow对象.我们可以在attach(...)方法中找到这个类的初始化.

 mWindow = new PhoneWindow(this, window);

继续跟进,找到PhoneWindowsetContentView(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;
        }
        ...
}

是不是看着很熟悉,我们去看看这个mFactorymFactory2是个什么东西?
最终发现,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图巩固一下

结语

有错请指出.

学无止境.

你可能感兴趣的:(工厂方法模式之Activity创建View)