(原创)我眼中的设计模式系列之简单工厂模式

Posted 每天进步一点点,好记性不如烂笔头

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(原创)我眼中的设计模式系列之简单工厂模式相关的知识,希望对你有一定的参考价值。

简单工厂模式

  在日常的软件开发中,我们一般都是按照模块来划分工作的。

场景一:

  试想我们现在有这么一个模块,为其他的模块提供服务,比如说我们调用了好几个外部接口,统一返回XML字符串,每个接口返回的XML格式都不同,有的嵌套数组,有的纯数组,有的就是普通的节点XML。但是我们项目需要的是json格式的数据,通常的做法是写几个类,直接new出对象调用,或者交给spring管理进行注入。不管如何这几个解析类都不是在同一个环境中,即使交由Spring管理,就站在这个模块的角度中来说,这几个类并并没有形成自己的模块化数据结构,而是分开和Spring的环境分散的耦合在一起了。代码的结构会非常差。

场景二:

  我们的业务模块中需要的类有可能是不相关的,毫无联系的,但是我们在一个比较大型的功能中需要同时用到这些类中的行为,这个时候我认为是可以使用工厂模式。即这些类实现同一个接口,使用工厂去维护他们,只针对我们需要的业务模块的维护,工厂类可以交给Spring管理,作为这个工厂和Spirng的接口,相当于跟Spring的环境有关系但是又不耦合。

  下面我举个小例子可以说明工厂模式的使用,直接上代码:

先创建具体行为的Animal接口

package com.bane.example1.executor;

/**
 * 
* @ClassName: Animal 
* @Description: TODO(定义动物的接口) 
* @author 于继伟
* @date 2017-10-20 下午10:06:49 
*
 */
public interface Animal {
}

创建具体动物行为的接口:

package com.bane.example1.executor;

/**
 * 
* @ClassName: CatExecutor 
* @Description: TODO(Cat的行为接口) 
* @author 于继伟
* @date 2017-10-20 下午10:02:29 
*
 */
public interface CatExecutor extends Animal {
    
    /**
     * 抓老鼠的行为
     */
    void catchMouse();
    
}
package com.bane.example1.executor;

/**
 * 
* @ClassName: DogExecutor 
* @Description: TODO(Dog的行为接口) 
* @author 于继伟
* @date 2017-10-20 下午10:00:12 
*
 */
public interface DogExecutor extends Animal {
    
    /**
     * 看家的方法
     */
    void door();
    
}
package com.bane.example1.executor;

/**
 * 
* @ClassName: SnakeExecutor 
* @Description: TODO(Snake的行为接口) 
* @author 于继伟
* @date 2017-10-20 下午10:04:46 
*
 */
public interface SnakeExecutor extends Animal {
    
    /**
     * 咬人的行为
     */
    void bite();
    
}

再创建具体的实现:

package com.bane.example1.executor.impl;

import com.bane.example1.executor.CatExecutor;

/**
 * 
* @ClassName: CatExecutorImpl 
* @Description: TODO(猫具体行为的实现) 
* @author 于继伟
* @date 2017-10-20 下午10:09:11 
*
 */
public class CatExecutorImpl implements CatExecutor {
    
    @Override
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
    
}
package com.bane.example1.executor.impl;

import com.bane.example1.executor.DogExecutor;

/**
 * 
* @ClassName: DogExecutorImpl 
* @Description: TODO(狗的行为的具体实现) 
* @author 于继伟
* @date 2017-10-20 下午10:09:08 
*
 */
public class DogExecutorImpl implements DogExecutor{
    
    @Override
    public void door() {
        System.out.println("狗看家");
    }
    
}
package com.bane.example1.executor.impl;

import com.bane.example1.executor.SnakeExecutor;

/**
 * 
* @ClassName: SnakeExecutorImpl 
* @Description: TODO(蛇具体行为) 
* @author 于继伟
* @date 2017-10-20 下午10:11:19 
*
 */
public class SnakeExecutorImpl implements SnakeExecutor {
    
    @Override
    public void bite() {
        System.out.println("蛇咬人");
    }
    
}

工厂环境中的具体行为者有了,现在创建工厂的接口和实现:

package com.bane.example1.factory;

import com.bane.example1.executor.Animal;

/**
 * 
* @ClassName: AnimalFactory 
* @Description: TODO(简单工厂接口) 
* @author 于继伟
* @date 2017-10-20 下午9:57:46 
*
 */
public interface AnimalFactory {
    
    /**
     * 根据类名创建Animal对象
     * @param className
     * @return
     */
    Animal createAnimal(String className);
    
}
package com.bane.example1.factory.impl;

import com.bane.example1.executor.Animal;
import com.bane.example1.factory.AnimalFactory;

/**
 * 
* @ClassName: AnimalFactoryImpl 
* @Description: TODO(动物工厂的具体实现) 
* @author 于继伟
* @date 2017-10-20 下午10:14:03 
*
 */
public class AnimalFactoryImpl implements AnimalFactory {
    
    @Override
    public Animal createAnimal(String className) {
        
        Animal animal = null;
        try {
            animal = (Animal) Class.forName(className).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        return animal;
    }
    
}

 

到此为止,我们的简单工厂创建结束,将动物放入动物的工厂中,我们需要用的时候只需要从工厂中获取动物的实例和行为,就可以使用了,测试类:

package com.bane.example1;

import com.bane.example1.executor.CatExecutor;
import com.bane.example1.executor.DogExecutor;
import com.bane.example1.executor.SnakeExecutor;
import com.bane.example1.factory.AnimalFactory;
import com.bane.example1.factory.impl.AnimalFactoryImpl;

/**
 * 
* @ClassName: Main 
* @Description: TODO(主方法测试) 
* @author 于继伟
* @date 2017-10-20 下午10:21:48 
*
 */
public class Main {
    
    public static void main(String[] args) {
        
        AnimalFactory animalFactory = new AnimalFactoryImpl();
        
        CatExecutor catExecutor = (CatExecutor) animalFactory.
                createAnimal("com.bane.example1.executor.impl.CatExecutorImpl");
        catExecutor.catchMouse();
        
        DogExecutor dogExecutor = (DogExecutor) animalFactory.
        createAnimal("com.bane.example1.executor.impl.DogExecutorImpl");
        dogExecutor.door();
        
        SnakeExecutor snakeExecutor = (SnakeExecutor) animalFactory.
        createAnimal("com.bane.example1.executor.impl.SnakeExecutorImpl");
        snakeExecutor.bite();
    }
    
}

控制台输出如下:

抓老鼠
狗看家
蛇咬人

需要说明的是,我们是用类名利用反射创建的实例,这样可以省去if else的判断,代码更加优雅。至于需要用什么样的方式去创建或者什么样的条件,这个可以自己灵活使用。至此,简单工厂到此为止。

 

 静态工厂

  静态工厂,其实跟上面的简单工厂没有任何的区别,无疑是工厂类中构造方法是私有的,方法都是静态的。直接上代码:

创建颜色的接口和具体的颜色实现:

package com.bane.example2.executor;

/**
 * 
* @ClassName: Color 
* @Description: TODO(定义颜色行为接口) 
* @author 于继伟
* @date 2017-10-21 下午12:11:28 
*
 */
public interface Color {
    
    void show();
    
}

具体实现:

package com.bane.example2.executor.impl;

import com.bane.example2.executor.Color;

/**
 * 
* @ClassName: Blue 
* @Description: TODO(Blue具体实现) 
* @author 于继伟
* @date 2017-10-21 下午12:13:17 
*
 */
public class Blue implements Color{
    
    @Override
    public void show() {
        System.out.println("这是蓝色");
    }
    
}
package com.bane.example2.executor.impl;

import com.bane.example2.executor.Color;

/**
 * 
* @ClassName: Red 
* @Description: TODO(Red具体实现) 
* @author 于继伟
* @date 2017-10-21 下午12:12:43 
*
 */
public class Red implements Color{
    
    @Override
    public void show() {
        System.out.println("我是红色");
    }
    
}
package com.bane.example2.executor.impl;

import com.bane.example2.executor.Color;

/**
 * 
* @ClassName: Yellow 
* @Description: TODO(Yellow具体实现) 
* @author 于继伟
* @date 2017-10-21 下午12:13:51 
*
 */
public class Yellow implements Color{
    
    @Override
    public void show() {
        System.out.println("这是黄色");
    }
    
}

最后创建我们的静态工厂:

package com.bane.example2.factory;

import com.bane.example2.executor.Color;

/**
 * 
* @ClassName: ColorFactory 
* @Description: TODO(静态工厂实现) 
* @author 于继伟
* @date 2017-10-21 下午12:16:49 
*
 */
public class ColorFactory {
    
    private ColorFactory(){}
    
    /**
     * 静态工厂获取Color对象的方法
     * @param className
     * @return
     */
    public static Color createColor(String className){
        Color color = null;
        try {
            color = (Color) Class.forName(className).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        return color;
    }
    
}

最后主方法测试静态工厂:

package com.bane.example2;

import com.bane.example2.executor.Color;
import com.bane.example2.factory.ColorFactory;

/**
 * 
* @ClassName: Main 
* @Description: TODO(主方法测试静态工厂) 
* @author 于继伟
* @date 2017-10-21 下午12:19:14 
*
 */
public class Main {
    
    public static void main(String[] args) {
        
        Color blue = ColorFactory.createColor
                ("com.bane.example2.executor.impl.Blue");
        blue.show();
        
        Color red = ColorFactory.createColor
                ("com.bane.example2.executor.impl.Red");
        red.show();
        
        Color yellow = ColorFactory.createColor
                ("com.bane.example2.executor.impl.Yellow");
        yellow.show();
        
    }
    
}

控制台输出:

package com.bane.example2;

import com.bane.example2.executor.Color;
import com.bane.example2.factory.ColorFactory;

/**
 * 
* @ClassName: Main 
* @Description: TODO(主方法测试静态工厂) 
* @author 于继伟
* @date 2017-10-21 下午12:19:14 
*
 */
public class Main {
    
    public static void main(String[] args) {
        
        Color blue = ColorFactory.createColor
                ("com.bane.example2.executor.impl.Blue");
        blue.show();
        
        Color red = ColorFactory.createColor
                ("com.bane.example2.executor.impl.Red");
        red.show();
        
        Color yellow = ColorFactory.createColor
                ("com.bane.example2.executor.impl.Yellow");
        yellow.show();
        
    }
    
}

控制台输出:

这是蓝色
我是红色
这是黄色

至此,静态工厂结束。

 

抽象工厂

  抽象工厂其实就是集中了好几种的工厂,常用的例子是我们的家有厨房,卫生间,房间。这三个都可以看作工厂。厨房里有菜刀,锅等等,是具体的事物行为;卫生间有马桶,淋浴头等具体的事物行为;房间有衣柜,床等具体的行为。今天我举了一个更容易理解的例子。我们的公司有各个部门,例如行政部管的是后勤服务等等,财务部管的是财务和结算等等,开发部负责软件的开发。公司就是一个抽象工厂,而这三个部门就是抽象工厂的具体工厂,抽象工厂定义行为,具体的工厂实现行为。至于我们刚才说的具体三个部门作为工厂,其实,每个部门内部还有很多员工和级别,这又可以继续往下分和扩展,但是我们一般不会那么做。因为那样类的结构过于复杂,跟我们设计模式的初衷不相符。下面直接上代码:

创建Department接口,没有任何行为,主要是为了统一部门的表现形式

 

package com.bane.example3.executor;

/**
 * 
* @ClassName: Company 
* @Description: TODO(公司的接口) 
* @author 于继伟
* @date 2017-10-21 下午12:36:38 
*
 */
public interface Department {
}

具体部门接口:

package com.bane.example3.executor;

/**
 * 
* @ClassName: CaiWuBuExecutor 
* @Description: TODO(财务部的行为接口) 
* @author 于继伟
* @date 2017-10-21 下午12:29:14 
*
 */
public interface CaiWuBuExecutor extends Department{
    
    /**
     * 结算的方法
     */
    void jiesuan();
    
}    
package com.bane.example3.executor;

/**
 * 
* @ClassName: KaiFabuExecutor 
* @Description: TODO(开发部的行为接口) 
* @author 于继伟
* @date 2017-10-21 下午12:28:42 
*
 */
public interface KaiFabuExecutor extends Department {
    
    /**
     * 开发的方法
     */
    void kaifa();
    
}
package com.bane.example3.executor;

/**
 * 
* @ClassName: XingZhengBuExecutor 
* @Description: TODO(行政部的行为接口) 
* @author 于继伟
* @date 2017-10-21 下午12:29:33 
*
 */
public interface XingZhengBuExecutor extends Department {
    
    /**
     * 后勤的方法
     */
    void houqin();
    
}

部门的具体实现:

package com.bane.example3.executor.impl;

import com.bane.example3.executor.CaiWuBuExecutor;

/**
 * 
* @ClassName: CaiWuBuExecutorImpl 
* @Description: TODO(财务部具体实现) 
* @author 于继伟
* @date 2017-10-21 下午12:47:44 
*
 */
public class CaiWuBuExecutorImpl implements CaiWuBuExecutor {

    @Override
    public void jiesuan() {
        System.out.println("财务部负责结算");
    }
    
}
package com.bane.example3.executor.impl;

import com.bane.example3.executor.KaiFabuExecutor;

/**
 * 
* @ClassName: KaiFabuExecutorImpl 
* @Description: TODO(开发部具体实现) 
* @author 于继伟
* @date 2017-10-21 下午12:48:17 
*
 */
public class KaiFabuExecutorImpl implements KaiFabuExecutor {

    @Override
    public void kaifa() {
        System.out.println("开发部负责开发");
    }
    
    
    
}
package com.bane.example3.executor.impl;

import com.bane.example3.executor.XingZhengBuExecutor;

/**
 * 
* @ClassName: XingZhengBuExecutorImpl 
* @Description: TODO(行政部具体实现) 
* @author 于继伟
* @date 2017-10-21 下午12:48:48 
*
 */
public class XingZhengBuExecutorImpl implements XingZhengBuExecutor {

    @Override
    public void houqin() {
        System.out.println("行政部负责后勤");
    }
    
}

跟之前一样,具体的行为有了,可以定义工厂类了:

package com.bane.example3.factory;

import com.bane.example3.executor.CaiWuBuExecutor;
import com.bane.example3.executor.KaiFabuExecutor;
import com.bane.example3.executor.XingZhengBuExecutor;

/**
 * 
* @ClassName: AbstractFactory 
* @Description: TODO(抽象工厂) 
* @author 于继伟
* @date 2017-10-21 下午12:23:46 
*
 */
public abstract class AbstractCompanyFactory {
    
    /**
     * 构建财务部
     * @param className
     * @return
     */
    public CaiWuBuExecutor createCaiwuBu(String className){return null;}
    
    /**
     * 构建开发部
     * @param className
     * @return
     */
    public KaiFabuExecutor createKaiFabu(String className){return null;}
    
    /**
     * 构建行政部
     * @param className
     * @return
     */
    public XingZhengBuExecutor createXingZhengBu(String className){return null;}
    
}
package com.bane.example3.factory.sub;

import com.bane.example3.executor.CaiWuBuExecutor;
import com.bane.example3.executor.Department;
import com.bane.example3.factory.AbstractCompanyFactory;

/**
 * 
* @ClassName: CaiWuBuFactory 
* @Description: TODO(财务部的工厂) 
* @author 于继伟
* @date 2017-10-21 下午12:26:53 
*
 */
public class CaiWuBuFactory extends AbstractCompanyFactory {

    @Override
    public CaiWuBuExecutor createCaiwuBu(String className) {
        Department department = null;
        try {
            department = (Department) Class.forName(className).newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (CaiWuBuExecutor) department;
    }

}
package com.bane.example3.factory.sub;

import com.bane.example3.executor.Department;
import com.bane.example3.executor.KaiFabuExecutor;
import com.bane.example3.factory.AbstractCompanyFactory;

/**
 * 
* @ClassName: KaiFaBuFactory 
* @Description: TODO(开发部的工厂) 
* @author 于继伟
* @date 2017-10-21 下午12:25:53 
*
 */
public class KaiFaBuFactory extends AbstractCompanyFactory {

    @Override
    public KaiFabuExecutor createKaiFabu(String className) {
        Department department = null;
        try {
            department = (Department) Class.forName(className).newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (KaiFabuExecutor) department;
    }

}
package com.bane.example3.factory.sub;

import com.bane.example3.executor.Department;
import com.bane.example3.executor.XingZhengBuExecutor;
import com.bane.example3.factory.AbstractCompanyFactory;

/**
 * 
* @ClassName: XingZhengBuFactory 
* @Description: TODO(行政部的工厂) 
* @author 于继伟
* @date 2017-10-21 下午12:26:12 
*
 */
public class XingZhengBuFactory extends AbstractCompanyFactory{

    @Override
    public XingZhengBuExecutor createXingZhengBu(String className) {
        Department department = null;
        try {
            department = (Department) Class.forName(className).newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (XingZhengBuExecutor) department;
    }

}

最后写主方法测试:

package com.bane.example3;

import com.bane.example3.executor.CaiWuBuExecutor;
import com.bane.example3.executor.KaiFabuExecutor;
import com.bane.example3.executor.XingZhengBuExecutor;
import com.bane.example3.factory.AbstractCompanyFactory;
import com.bane.example3.factory.sub.CaiWuBuFactory;
import com.bane.example3.factory.sub.KaiFaBuFactory;
import com.bane.example3.factory.sub.XingZhengBuFactory;

/**
 * 
* @ClassName: Main 
* @Description: TODO(抽象工厂测试) 
* @author 于继伟
* @date 2017-10-21 下午12:22:48 
*
 */
public class Main {
    
    public static void main(String[] args) {
        //1.获取具体的工厂
        //财务部的工厂
        AbstractCompanyFactory caiwuFactory = new CaiWuBuFactory();
        
        //开发部的工厂
        AbstractCompanyFactory kaifaFactory = new KaiFaBuFactory();
        
        //行政部的工厂
        AbstractCompanyFactory xingZhengFactory = new XingZhengBuFactory();
        
        //2.从工厂中获取具体的部门职能
        //财务职能
        CaiWuBuExecutor caiwu = caiwuFactory.createCaiwuBu
                ("com.bane.example3.executor.impl.CaiWuBuExecutorImpl");
        
        //开发职能
        KaiFabuExecutor kaifa = kaifaFactory.createKaiFabu
                ("com.bane.example3.executor.impl.KaiFabuExecutorImpl");
        
        //后勤职能
        XingZhengBuExecutor xingzheng = xingZhengFactory.createXingZhengBu
                ("com.bane.example3.executor.impl.XingZhengBuExecutorImpl");
        
        caiwu.jiesuan();
        kaifa.kaifa();
        xingzheng.houqin();
    }
    
}

控制台输出:

财务部负责结算
开发部负责开发
行政部负责后勤

 

   上面就是我们工厂模式常用的三种表现形式,从上面的代码我们不难看出接口的作用,面向接口编程是JAVA开发中非常重要的一个理念,或者说是思想,根据SOA的思想来说,暴露出来的一定是接口,接口实现的对象类型的控制和扩展,在面向对象程序的设计中具有非常至关重要的意义。至于面向接口编程,大家可以搜索一下相关的文章去阅读。

  其实我们的Spring就是一个非常大的工厂模式,阅读过源码的同学可以知道,Spring基于BeanFactory,创建出Bean,但是又维护着自己的数据结构,源于工厂,但是比工厂的设计复杂太多太多。工厂模式我的理解就是这样。

 

以上是关于(原创)我眼中的设计模式系列之简单工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式从青铜到王者第五篇:创建型模式之简单工厂模式( Simple Factory Pattern )

设计模式回顾系列之简单工厂模式

《C#零基础入门之百识百例》(五十六)多态介绍 -- 简单工厂模式

[设计模式系列] 抽象工厂

C++进阶系列之设计模式---设计模式的核心思想

设计模式之单例模式