结合Android学设计模式--工厂方法(FactoryMethod)

简单工厂模式

简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式中包含的角色及其职责
1.工厂(Creator)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
2.抽象(Product)角色 简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
3.具体产品(Concrete Product)角色 简单工厂模式所创建的具体实例对象

结构:



在android中的Connection类中使用到了这个类:



其中Connection这个抽象类,既充当抽象产品类,也充当具体工厂类。

因为这种情况下,我们往往需要的是马上生产子类,getConnection方法往往是静态的,所以简单工厂,也叫静态工厂方法。

abstract class Connection{
    static Connection getConnection(
            Context context, HttpHost host, HttpHost proxy,
            RequestFeeder requestFeeder) {

        if (host.getSchemeName().equals("http")) {
            return new HttpConnection(context, host, requestFeeder);
        }

        // Otherwise, default to https
        return new HttpsConnection(context, host, proxy, requestFeeder);
    }
}  

在Android中,我们经常使用静态工厂方法的地方应该是创建Bitmap对象的时候,例如通过资源id获取Bitmap对象。

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher) ;
可以看到源码中,decodeResource(Resourcesres,intid)函数调用的是decodeResource(Resourcesres,intid, Options opts), 在decodeResource函数中,最终把传递进来的资源id解析成InputStream, 然后称调用decodeResourceStream(res, value, is, null,opts)方法。decodeResourceStream初始化一些配置和像素信息以后,调用decodeStream(is,pad,opts),最终调用nativeDecodeAsset或者nativeDecodeStream来构建Bitmap对象,这两个都是native方法( Android中使用Skia库来解析图像 ),本文不进行讨论。最后调用finishDecode函数来设置像素、配置信息、缩放等参数,最终返回Bitmap对象。


BitmapFactory中的decodeFile、decodeByteArray工厂方法都是这么一个类似的过程,BitmapFactory通过不同的工厂方法与传递不同的参数调用不同的图像解析函数来构造Bitmap对象。


优点:
1、分工明确,各司其职;
2、客户端不再创建对象,而是把创建对象的职责交给了具体的工厂去创建;
3、使抽象与实现分离, 客户程序不知道具体实现;
4、具名工厂函数,更能体现出代码含义。
缺点:
1、工厂的静态方法无法被继承;
2、代码维护不易,对象要是很多的话,工厂是一个很庞大的类;
3、违反开闭原则,如果有新的产品加入到系统中就要修改工厂类。


什么是工厂方法模式?

工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

模式中包含的角色及其职责

1.抽象工厂(Creator)角色 工厂方法模式的核心,任何工厂类都必须实现这个接口。
2.具体工厂( Concrete Creator)角色 具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
3.抽象(Product)角色 工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
4.具体产品(Concrete Product)角色 工厂方法模式所创建的具体实例对象

工厂方法模式和简单工厂模式比较

工厂方法模式与简单工厂模式在结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。 当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对
象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。 工厂方法模式退化后可以演变成简单工厂模式。

标准的工厂方法结构图


先抽象的产品类,抽象的工厂类,然后用客户端具体的工厂生产相应的具体的产品,但是客户端并不知道具体的产品是怎么生产的,生产的过程封装在工厂里。所以说,某种程度上,工厂方法模式改变了我们直接用new创建对象的方式,一个很好的开始,意义重大。
以ThreadFactory为例:



这张图其实和原本的结构图有细微的区别,那就是参数化得工厂,而且从业务意义上也有些不同,但是思想是一样的。
我们来看下具体的代码:

//抽象产品
public interface Runnable {
    public abstract void run();
}

//抽象工厂
public interface ThreadFactory {
    Thread newThread(Runnable r);
} 
比如AsyncTask类中工厂的具体实现如下:

//工厂实现类
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    }
};
//那么产品类在哪里呢?
//做为参数Runnable r,我们可以创建千千万万个此系列的产品类
//同理,我们可以创建另外类似的工厂,生产某种专门的线程,非常容易扩展