Android 源码中的工厂方法模式

首发: Android 源码中的工厂方法模式

写在前面的话

在之前一篇《Android 源码中的静态工厂方法》中我一起研究了工厂模式三兄弟中最简单的静态工厂方法。今天我们来一起看看三兄弟中的老二————工厂方法模式,以及它在Android源码中的体现。


今天我们先来模拟一个场景,把这三兄弟拎出来给大家瞅瞅,以免以后大家认错。


  • 今天我们决定进军手机行业,手机名字叫做aPhone。我们要做一个aPhone1的样品。————我们的直接new一个aPhone1对象就好了

  • 我们的aPhone1卖的巨火,挡都挡不住,我们要出aPhone2、aPhone3、aPhone4等等一系列手机。————我们可以通过简单工厂方法来生产手机(老三)

  • 我们的aPhone系列手机配置比较高,考虑到市场上对低端产品的需求,我们要做aPhoneNote系列手机。————我们可以通过工厂方法模式来生产(老二)

  • 由于我们aPhone6系列手机的屏幕生产时出现了问题,导致手机寿命降低,给公司造成了很大的损失。现在我们要从零件方面来把控产品质量,屏幕、电池、主板等零件的质量我们都要做质检。————我们可以通过抽象工厂来生产(老大)


这就是工厂三兄弟。


工厂方法模式


定义


工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。


工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。


结构


工厂方法模式所涉及到的角色:


  • Product(抽象产品角色):它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。

  • ConcreteProduct(具体产品角色):具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

  • Factory(抽象工厂角色):这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。

  • ConcreteFactory(具体工厂角色):它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。


实现


我们用我们上边手机的例子来实现。


抽象产品角色


abstractclassAPhone{  

    //所有产品类的公共业务方法  

    publicvoidmethodSame(){  

        //公共方法的实现  

    }  

 

    //声明抽象业务方法  

    publicabstractvoidmethodDiff();  

}


具体产品角色类,这里我们只说一类,比如我们的aPhoneNote系列手机


classAPhoneNote1extendsAPhone{  

    //实现业务方法  

    publicvoidmethodDiff(){  

        //业务方法的实现  

    }  

}


抽象工厂角色


abstractclassFactory{  

    //静态工厂方法  

    publicabstractAPhone createProduct(Stringarg)

}


具体工厂角色,这里我们只说生产aPhoneNote系列手机的工厂


classConcreteFactory{  

    //静态工厂方法  

    publicAPhone createProduct(Stringarg){  

        APhoneaPhoneNote = null;  

        if(arg.equalsIgnoreCase("1")){  

            aPhoneNote = newAPhoneNote1();  

            //初始化设置product  

        }  

        elseif(arg.equalsIgnoreCase("2)){  

            aPhoneNote = newAPhoneNote2();  

            //初始化设置product  

        }  

        returnaPhoneNote;  

    }  

}


使用场景


  • 需要创建复杂对象

  • 需要灵活、可扩展的框架,且具体类型不多


Android中工厂方法模式的应用


Java中的类集框架


我们在开发中会用到很多数据结构,比如ArrayList,HashMap等。我们先来看下Java中Collection部分的类集框架的简要UML图。



我们知道Iterator是迭代器,用来遍历一个集合中的元素。而不同的数据结构遍历的方式是不一样的,所以迭代器的实现也是不同的。使用工厂方法模式将迭代器的具体类型延迟到具体容器类中,比较灵活,容易扩展。


List和Set继承自Collection接口,Collection接口继承于Iterable接口。


publicinterfaceIterable<T>{

    /**

     * Returns an iterator over elements of type {@code T}.

     *

     * @return an Iterator.

     */

    Iterator<T>iterator();

 

    //省略部分代码

}


所以List和Set接口也会继承该方法。然后我们常用的两个间接实现类ArrayList和HashSet中的iterator方法就给我们构造并返回了一个迭代器对象。


我们找到ArrayList类,查看iterator方法的实现。


@Override

publicIterator<E>iterator(){

    returnnewArrayListIterator();

}


ArrayListIterator类型定义如下:


privateclassArrayListIteratorimplementsIterator<E>{

    /** Number of elements remaining in this iteration */

    privateintremaining = size;

 

    /** Index of element that remove() would remove, or -1 if no such elt */

    privateintremovalIndex = -1;

 

    /** The expected modCount value */

    privateintexpectedModCount = modCount;

 

    publicbooleanhasNext(){

        returnremaining != 0;

    }

 

    @SuppressWarnings("unchecked")publicEnext(){

        ArrayList<E>ourList = ArrayList.this;

        intrem = remaining;

        if(ourList.modCount != expectedModCount){

            thrownewConcurrentModificationException();

        }

        if(rem == 0){

            thrownewNoSuchElementException();

        }

        remaining = rem - 1;

        return(E)ourList.array[removalIndex = ourList.size - rem];

    }

 

    publicvoidremove(){

        Object[]a = array;

        intremovalIdx = removalIndex;

        if(modCount != expectedModCount){

            thrownewConcurrentModificationException();

        }

        if(removalIdx < 0){

            thrownewIllegalStateException();

        }

        System.arraycopy(a,removalIdx + 1,a,removalIdx,remaining);

        a[--size] = null;  // Prevent memory leak

        removalIndex = -1;

        expectedModCount = ++modCount;

    }

}


我们看到这个类实现了Iterator接口,接口的定义如下:


publicinterfaceIterator<E>{

 

    booleanhasNext();

 

    Enext();

 

    defaultvoidremove(){

        thrownewUnsupportedOperationException("remove");

    }

 

    defaultvoidforEachRemaining(Consumer<?superE>action){

        Objects.requireNonNull(action);

        while(hasNext())

            action.accept(next());

    }

}


我们基本的结构也分析完了,接下来对号入座,看一看具体是如何实现工厂方法模式的。


Iterator————>Product;ArrayListIteratorr————>ConcreteProduct。


Iterable/List————>Factory;ArrayList————>ConcreteFactory。


工厂方法使一个类的实例化延迟到子类,对应着将迭代器Iterator的创建从List延迟到了ArrayList。这就是工厂方法模式。


瞎总结


看是看完了,但是,总要给我们一个这么做的理由吧?


个人认为,这样设计使得我们的代码结构变得更清晰,同是比较容易扩展,因为我们已经定义好了一套标准,只要按照规矩来就好了。


同时耦合度降低了,高层模块只需要知道产品的抽象类,无所谓具体怎么实现这个产品。


关于Java和Android大牛频道

Java和Android大牛频道是一个数万人关注的探讨Java和Android开发的公众号,分享和原创最有价值的干货文章,让你成为这方面的大牛!

我们探讨android和Java开发最前沿的技术:android性能优化 ,插件化,跨平台,动态化,加固和反破解等,也讨论设计模式/软件架构等。由群来自BAT的工程师组成的团队

关注即送红包,回复:“百度” 、“阿里”、“腾讯” 有惊喜!!!关注后可用入微信群。群里都是来自百度阿里腾讯的大牛。

欢迎关注我们,一起讨论技术,扫描和长按下方的二维码可快速关注我们。搜索微信公众号:JANiubility。


公众号:JANiubility

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值