首页 > 代码库 > 工厂模式

工厂模式

先说下我对工厂模式的理解:当我们需要某个对象时,最直接的办法是看到这个对象就拿过来。但是当对象非常多的时候,找起来就很不方便。这时就需要一个中介来帮助我们取得想要的东西,这个中介就是工厂(factory)。

 

工厂模式可分为三个分类(简单工厂模式Simple Factory、 工厂方法模式Factory Method、 抽象工厂模式Abstract Factory)

 

我来模拟一个场景:动物园管理员每天都要确保动物的健康,确定动物健康的一种简单方法就是听一听动物的叫声是不是正常。这样,管理员就需要随时找到任一种动物以确定动物的情况。下面是动物相关类(至于动物园为什么有猫和狗大家就不要太计较了……):

 

interface:Animal(动物的接口)

package com.captain.factory;/** * <P>Title:动物接口<p> * @author 船长工作室 */public interface Animal {    void call();}
package com.captain.factory;/** * <p>Title:猫<p> * @author 船长工作室 */public class Cat implements Animal {    /**     * 猫叫     * @param 无     * @return void     */    public void call() {        System.out.print("meow");    }}package com.captain.factory;/** * <p>Title:狗<p> * @author 船长工作室 */public class Dog implements Animal {    /**     * 狗叫     * @param 无     * @return void     */    public void call() {        System.out.print("bark");    }}package com.captain.factory;/** * <p>Title:老虎<p> * @author 船长工作室 */public class Tiger implements Animal {    /**     * 老虎叫     * @param 无     * @return void     */    public void call() {        System.out.print("roar");    }}

下面先介绍简单工厂模式:

class:SimpleFactory(简单工厂)

package com.captain.factory;/** * <p>Title:简单工厂模式-工厂类<p> * @author 船长工作室 */public class SimpleFactory {    /**     * 召唤动物     * @param s 召唤动物的种类     * @return animal 该种类的动物实例     */    public static Animal search(String s){        Animal animal = null;        if ("cat".equals(s)){//判断召唤动物的种类            animal = new Cat();        }else if("dog".equals(s)){            animal = new Dog();        }else if("tiger".equals(s)){            animal = new Tiger();        }        return animal;//返回找到的动物    }}package com.captain.factory;/** * <p>Title:简单工厂模式-动物管理员<p>  * @author 船长工作室 */public class SimpleManager {    /**     * 动物管理员找到所需动物,并让该动物叫出声来     * @param args     */    public static void main(String[] args) {        Animal animal = SimpleFactory.search("dog");//从工厂中获得指定类型动物        if ( animal == null ){            System.out.print("can‘t find this kind of animal!");            return;//没有找到指定动物,返回        }        animal.call();//让得到的动物叫出声来    }}

 

简单工厂通过一个工厂对象来管理、查询各个对象。比较简单、方便。但是当添加新的动物时,我们不仅要添加新的动物类,还要修改工厂中的逻辑(if()...else if()...else if()...)。当逻辑比较复杂时,就会很混乱……

 

工厂方法模式就解决了这个问题:

Interface:CallAnimal(召唤动物)

package com.captain.factory;/** * <p>Title:召唤动物接口<p> * @author 船长工作室 */public interface CallAnimal {    /**     * 得到召唤的动物     * @return Animal 召唤的动物      */    Animal callAnimal();}package com.captain.factory;/** * <p>Title:得到猫<p> * @author 船长工作室 */public class CallCat implements CallAnimal {    /**     * 得到猫      * @return Cat 猫     */    public Animal callAnimal() {        return new Cat();    }}package com.captain.factory;/** * <p>Title:得到狗<p> * @author 船长工作室 */public class CallDog implements CallAnimal {    /**     * 得到狗      * @return Dog 狗     */    public Animal callAnimal() {        return new Dog();    }}package com.captain.factory;/** * <p>Title:得到老虎<p> * @author 船长工作室 */public class CallTiger implements CallAnimal {    /**     * 得到老虎      * @return Tiger 老虎     */    public Animal callAnimal() {        return new Tiger();    }}package com.captain.factory;/** * <p>Title:工厂方法模式-动物管理员<p> * @author 船长工作室 */public class MethodManager {    /**     * 动物管理员通过指定工厂找到所需动物,并让该动物叫出声来     * @param args     */    public static void main(String[] args){        CallAnimal callAni = new CallCat();//调用指定动物工厂        Animal animal = callAni.callAnimal();//获得指定        animal.call();//让动物叫    }}

工厂方法模式通过一个工厂一个对象的形式,解决了上述问题。当需要一个新的对象时,只需新建一个对应的工厂,并在使用时调用相应的工厂就好了。但是这种方式会随着对象的增加而出项很多很多的工厂对象……

 

下面介绍抽象工厂模式:

我认为抽象工厂模式适用于有分类的情况。比如HP、DELL、Lenov都有台式机和笔记本、智能手机出售。这时可以为每个品牌建立一个工厂,工厂里得到该品牌的产品(台式机、笔记本、智能手机)。想买什么产品,将调用相应品牌的对应方法,得到该产品。

还以我们的动物园管理员举例。现在我们的管理员需要对动物按性别进行管理。这样,我们就需要建立雄性和雌性两个接口。

Interface:Male(雄性)

package com.captain.factory;/** * <p>Title:雄性<p> * @author 船长工作室 */public interface Male {}package com.captain.factory;/** * <p>Title:雌性<p> * @author 船长工作室 */public interface Female {}package com.captain.factory;/** * <p>Title:公猫<p> * @author 船长工作室 */public class MaleCat extends Cat implements Male{    /**     * 公猫叫     * @param 无     * @return void     */    public void call() {        System.out.print("male-meow");    }}package com.captain.factory;/** * <p>Title:公狗<p> * @author 船长工作室 */public class MaleDog extends Dog implements Male{    /**     * 公狗叫     * @param 无     * @return void     */    public void call() {        System.out.print("male-bark");    }}package com.captain.factory;/** * <p>Title:公老虎<p> * @author 船长工作室 */public class MaleTiger extends Tiger implements Male{    /**     * 公老虎叫     * @param 无     * @return void     */    public void call() {        System.out.print("male-roar");    }}package com.captain.factory;/** * <p>Title:母猫<p> * @author 船长工作室 */public class FemaleCat extends Cat implements Female{    /**     * 母猫叫     * @param 无     * @return void     */    public void call() {        System.out.print("female-meow");    }}package com.captain.factory;/** * <p>Title:母狗<p> * @author 船长工作室 */public class FemaleDog extends Dog implements Female{    /**     * 母狗叫     * @param 无     * @return void     */    public void call() {        System.out.print("female-bark");    }}package com.captain.factory;/** * <p>Title:母老虎<p> * @author 船长工作室 */public class FemaleTiger extends Tiger implements Female{    /**     * 母老虎叫     * @param 无     * @return void     */    public void call() {        System.out.print("female-roar");    }}

分类完毕之后,我们需要定义一个工厂接口,这个接口能够获得所有种类的对象(比如猫、狗、老虎)

Interface:AbstractFactory(抽象工厂)

 

package com.captain.factory;/** * <p>Title:抽象工厂<p> * @author 船长工作室 */public interface AbstractFactory {    /**     * 获得猫     * @return*/    Cat callCat();        /**     * 获得狗     * @return*/    Dog callDog();        /**     * 获得老虎     * @return 老虎     */    Tiger callTiger();}有了接口,我们要实现两个具体工厂(分别是公的和母的……)class:MaleFactory(雄性工厂)package com.captain.factory;/** * 获得雄性动物 * @author 船长工作室 */public class MaleFactory implements AbstractFactory {    /**     * 获得公猫     * @return 公猫     */    public Cat callCat() {        return new MaleCat();    }    /**     * 获得公狗     * @return 公狗     */    public Dog callDog() {        return new MaleDog();    }    /**     * 获得公老虎     * @return 公老虎     */    public Tiger callTiger() {        return new MaleTiger();    }}class:FemaleFactory(雌性工厂)package com.captain.factory;/** * 获得雌性动物 * @author 船长工作室 */public class FemaleFactory implements AbstractFactory {    /**     * 获得母猫     * @return 母猫     */    public Cat callCat() {        return new FemaleCat();    }    /**     * 获得母狗     * @return 母狗     */    public Dog callDog() {        return new FemaleDog();    }    /**     * 获得母老虎     * @return 母老虎     */    public Tiger callTiger() {        return new FemaleTiger();    }}有了以上两个工厂,我们就可以获得其中一种性别的动物了class:AbstractManager(动物园管理员)package com.captain.factory;/** * <p>Title:抽象工厂模式-动物管理员<p>  * @author 船长工作室 */public class AbstractManager {    /**     * 动物管理员找到所需动物,并让该动物叫出声来     * @param args     */    public static void main(String[] args) {        FemaleFactory maleFac = new FemaleFactory();//建立雌性动物工厂        Animal animal = maleFac.callTiger();//从工厂中获得指定类型动物        if ( animal == null ){            System.out.print("can‘t find this kind of animal!");            return;//没有找到指定动物,返回        }        animal.call();//让得到的动物叫出声来    }}

可见,管理员通过建立雌性动物工厂,得到了母老虎……

采用抽象工厂时,有几个分类就有几个工厂(HP、DELL、Lenovo等),每个工厂里,有几种产品就有几个方法(createDesktop、createNotebook、createPhone等)。

 

工厂模式