Android中的设计模式-工厂方法模式

简单工厂&工厂方法

一直以来总是分不清简单工厂,工厂方法,抽象工厂这三个设计模式的区别,倒不是不理解其区别,而是总是记忆混淆,傻傻分不清楚,所以再重新总结一下区别,并记录下来,下次再混淆时,可以拿出来看看。这节先说简单工厂和工厂方法,下一节再说抽象工厂。

工厂方法中其实就包含了简单工厂,简单工厂也称为静态工厂方法,

简单工厂模式(Simple Factory)

类图

技术分享
简单工厂模式又称为静态工厂方法模式,是工厂方法模式的一种,简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。注意这里工厂类传入的参数,是工厂类新建产品的依据,可以是一个字符串,也可以是自己定义的Enum或者Int值。

以一个汽车工厂为例,可以生产3种不同类型的汽车,SUV,Sedan,MPV,每个汽车都有drive方法。如果不使用简单工厂而是直接创建的话,如下面的例子。

public class User {
    public static SUV suv;
    public static void main(String[] args) {
        suv=new SUV();
        suv.drive();
    }

}
class SUV{
    public void drive(){
        System.out.println("SUV is driving");
    }
}
class Sedan{
    public void drive(){
        System.out.println("Sedan is driving");
    }
}
class MPV{
    public void drive(){
        System.out.println("MPV is driving");
    }
}

乍看起来没问题,想要什么产品,那就直接新建一个就好了,不过问题在于,对于使用产品的类,只能持有对应产品的对象,例如上面的例子,我持有SUV的对象,然后新建SUV的对象,当有一天有了新的产品了,并且需要替换SUV。还需要修改使用的主体。这就使使用产品的主体和产品紧紧耦合在了一起。不利于代码的复用和拓展。

把上面的代码稍微修改一下,将所有车辆抽象为一个Vehicle接口,让User持有一个Vehicle对象,新建一个工厂类,根据传入的参数不同,返回不同的对象给User使用。并且工厂类创建产品的函数是静态的,这样就不需要先创建一个工厂类了。

代码:


interface Vehicle{
    public void drive();
}
class SUV implements Vehicle {
    @Override
    public void drive(){
        System.out.println("SUV is driving");
    }
}
class Sedan implements Vehicle{
    @Override
    public void drive() {
        System.out.println("Sedan is driving");
    }

}
class MPV implements Vehicle{
    @Override
    public void drive(){
        System.out.println("MPV is driving");
    }
}

enum VehcleType{
    suv,sedan,mpv
}
public class SimpleFactory {
    public static Vehicle makeVehicle(VehcleType type){
        switch(type){
        case suv:
            return new SUV();
        case sedan:
            return new Sedan();
        case mpv:
            return new MPV();
        default:
            break;
        }
        return null;

    }
}

测试代码:


public class User {
    public static Vehicle mVehicle;
    public static void main(String[] args) {
        mVehicle=SimpleFactory.makeVehicle(VehcleType.suv);
        mVehicle.drive();
    }

}

这样就好多了。不过有些情况还是不够好,比如:
当我需要生产一种新的车型,比如敞篷车 Convertible. 但是我在SimpleFactory.makeVehicle时,并没有这种车型,那就需要修改SimpleFactory类让它增加一个case判断,并新建一个Convertible对象。但是我们并不希望SimpleFactory这个工厂类开放给用户,也就造成了没办法去增加车型。 如何才能让User任意的增加车型呢? 这就扩展出了工厂方法模式

工厂方法模式(Factory Method)

继续上面的说,User可以只知道一个Vehicle接口对象和一个Factory接口对象,对于SUV来说它实现了Vehicle接口,同时也需要SUVFactory来实现Factory接口并创建它,这样对User来说,只需要创建一个SUVFactory对象,然后通过SUVFactory类创建一个SUV对象。 如果客户自己想增加一个Convertible产品。那只需要实现自己的Convertible类和ConvertibleFactory类。然后用同样的方式生产即可。

类图

技术分享

代码:

车辆相关

public interface Vehicle {
    public void drive();
}
class SUV implements Vehicle {
    @Override
    public void drive(){
        System.out.println("SUV is driving");
    }
}
class Sedan implements Vehicle{
    @Override
    public void drive() {
        System.out.println("Sedan is driving");
    }

}
class MPV implements Vehicle{
    @Override
    public void drive(){
        System.out.println("MPV is driving");
    }
}

工厂相关

public interface Factory {
    public Vehicle makeVehicle();

}

class SUVFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new SUV();
    }

}
class SedanFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new Sedan();
    }

}
class MPVFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new MPV();
    }

}

客户类:
public class User {
public static Vehicle mVehicle;
public static Factory mFactory;
public static void main(String[] args) {
mFactory=new SUVFactory();
mVehicle=mFactory.makeVehicle();
mVehicle.drive();
}

}

这时,我们想要改生产Convertible车辆,只需要增加Convertible和对应工厂,并修改客户类的实现即可:

class Convertible implements Vehicle{
    @Override
    public void drive(){
        System.out.println("Convertible is driving");
    }
}
class ConvertibleFactory implements Factory{
    @Override
    public Vehicle makeVehicle() {

        return new Convertible();
    }

}
public class User {
    public static Vehicle mVehicle;
    public static Factory mFactory;
    public static void main(String[] args) {
        mFactory=new ConvertibleFactory();
        mVehicle=mFactory.makeVehicle();
        mVehicle.drive();
    }

}

这时,生产出来的就是Convertible产品了。
设计模式的应用还是要根据其使用场景来决定,简单工厂升级为工厂方法,是因为需要封装工厂类,提供给客户类最大的自由和扩展性,但又对工厂的内部逻辑进行封装。
但不是说简单工厂就没有工厂方法好用,当客户类User本身也是内部封装的一部分,我们可以很方便的去修改工厂类,或者产品的增加可能很小,比如Phone,本来就只有GSMPhone,CDMAPhone,过了很久,突然出现了CDMALTEPhone,那也只需要在工厂类中增加这个类的生产即可。也许再出现一个新的XXXPhone也要几年之后了。

Android中的工厂方法

简单工厂

Android源码中有很多的工厂方法的使用,其中大多是静态工厂方法,也即是最开始说的简单工厂,前面也说过了,使用什么工厂是根据需求来看的,静态工厂方法是工厂方法的一个特例,虽然不似工厂方法那么灵活,但是对于很多不需要创建多个工厂来建造产品的情况下,静态工厂方法反而简单快捷。

例如BitmapFactory,通过public static Bitmap decodeFile(String pathName)静态方法,从文件中读取并新建Bitmap对象。
还比如Telephony中的PhoneFactory,通过public static void makeDefaultPhones(Context context) 静态方法创建,并通过PhoneFactory.getDefaultPhone()获取创建好的
还有NetworkStatsFactory,WebViewFactory这些都是简单工厂的应用。
除了Framework,很多系统应用也用到了工厂方法,就不一一列举了。

工厂方法

Java库中的ThreadFactory类作为抽象工厂,定义如下:

public interface ThreadFactory {
    Thread newThread(Runnable r);
}

Android中常用的AsyncTask,在其中就新建了一个具体的工厂(还有MMS应用中的BackgroundLoaderThreadFactory的实现,类似):

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

ThreadFactory的使用一般用在作为新建ThreadPoolExecutor的参数,在ThreadPoolExecutor中调用getThreadFactory().newThread()来新建一个工作线程,这里面Runnable可以理解为抽象产品,而Thread则是具体产品。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。