zoukankan      html  css  js  c++  java
  • (原创)我眼中的设计模式系列之简单工厂模式(一)

    简单工厂模式

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

    场景一:

      试想我们现在有这么一个模块,为其他的模块提供服务,比如说我们调用了好几个外部接口,统一返回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,但是又维护着自己的数据结构,源于工厂,但是比工厂的设计复杂太多太多。工厂模式我的理解就是这样。

  • 相关阅读:
    ZOJ2334 Monkey King 并查集 STL
    ZOJ2286 Sum of Divisors 筛选式打表
    ZOJ2105 终于找到错误
    ZOJ-2091-Mean of Subsequence (反证法的运用!!)
    【9929】潜水员
    【9928】混合背包
    【t077】宝物筛选
    【9927】庆功会
    【9926】完全背包
    【9925】0/1背包
  • 原文地址:https://www.cnblogs.com/yujiwei/p/7705611.html
Copyright © 2011-2022 走看看