zoukankan      html  css  js  c++  java
  • 工厂模式(简单、普通、抽象)

    概述

    属于创建型设计模式,需要生成的对象叫做产品 ,生成对象的地方叫做工厂 。

    使用场景:

      1、在任何需要生成复杂对象的地方,都可以使用工厂方法模式。

      2、直接用new可以完成的不需要用工厂模式

    一、简单(静态)工厂

     我喜欢吃粉,抽象一个粉基类(或者接口),这是产品的抽象类

    package com.wbg.FactoryMode;
    
    public abstract class Powder {
        /**
         * 描述粉
         * 桂林米粉、柳州螺蛳粉
         */
        public abstract void desc();
    }

    来一份桂林米粉(具体的产品类)

    package com.wbg.FactoryMode;
    
    public class GlPowder extends Powder {
        @Override
        public void desc() {
            System.out.println("桂林米粉,很好吃,上海的很贵,在家才5-6块钱");
        }
    }

    我老家的螺蛳粉(具体的产品类)

    package com.wbg.FactoryMode;
    
    public class LsfPowder extends Powder {
    
        @Override
        public void desc() {
            System.out.println("螺蛳粉,不错,老家6块钱,珠海10多块");
        }
    }

    准备工作做完了,我们来到一家“粉店”(简单工厂类),菜单如下:

    package com.wbg.FactoryMode;
    
    public class SimplePowderFactor {
        public static final int TYPE_LZ = 1;//桂林米粉
        public static final int TYPE_PM = 2;//螺蛳粉
        public static Powder createNoodles(int type) {
        if(type==1){
            return new GlPowder();
        }else {
            return new LsfPowder();
        }
        }
    }

    简单粉店就提供二种面条(产品),你说你要啥,他就给你啥。这里我点了桂林米粉:

    package com.wbg.FactoryMode;
    
    /**
    * 简单工厂模式
    */
    public class Customer { public static void main(String[] args) { Powder powder=SimplePowderFactor.createNoodles(SimplePowderFactor.TYPE_LZ); powder.desc(); } }

    特点

    1、 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。

    2、 create()方法通常是静态的,所以也称之为静态工厂。

    缺点

    1、 扩展性差(我想增加一种粉,除了新增一个粉产品类,还需要修改工厂类方法)

    2 、不同的产品需要不同额外参数的时候 不支持。

    二、另一种简单工厂(反射):

    利用反射Class.forName(tClass.getName()).newInstance()实现的简单工厂:

    package com.wbg.FactoryMode;
    
    public class StaticPowderFactor {
        /**
         * 传入Class实例化粉产品类
         *
         * @param tClass
         * @param <T>
         * @return
         */
        public static <T extends Powder>T createPowder(Class<T> tClass){
            T result=null;
            try {
                result= (T) Class.forName(tClass.getName()).newInstance();
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
            return result;
        }
    }

    点粉:

    package com.wbg.FactoryMode;
    
    public class Customer {
        public static void main(String[] args) {
            Powder powder=StaticPowderFactor.createPowder(new LsfPowder().getClass());
            powder.desc();
        }
    }

    特点

    1 它也是一个具体的类,非接口 抽象类。但它的create()方法,是利用反射机制生成对象返回,好处是增加一种产品时,不需要修改create()的代码。

    缺点

    1 因为Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂。

    2 不同的产品需要不同额外参数的时候 不支持。

    三、多方法工厂

    上面都有一个缺点:不同的产品需要不同额外参数的时候 不支持。

    如果使用时传递的type、Class出错,将不能得到正确的对象,容错率不高。

    多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。

    工厂:

    package com.wbg.FactoryMode;
    
    public class VariedPowderFactor {
        /**
         * 生产桂林米粉
         * @return
         */
        public static Powder createGl(){
            return new GlPowder();
        }
        /**
         * 生产螺丝粉
         * @return
         */
        public static Powder createLsf(){
            return new LsfPowder();
        }
    }

    点餐:

    package com.wbg.FactoryMode;
    
    public class Customer {
        public static void main(String[] args) {
            Powder glpowder=VariedPowderFactor.createGl();
            glpowder.desc();
    
            Powder lsfpowder=VariedPowderFactor.createLsf();
            lsfpowder.desc();
        }
    }

    四、普通工厂

    普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。(一般->特殊)

    工厂(抽象工厂类),作用就是生产粉:

    package com.wbg.FactoryMode;
    
    public abstract  class PowderFactory {
        public abstract Powder create();
    }

    我老家的螺蛳粉(具体工厂子类):

    package com.wbg.FactoryMode;
    
    public class createLsfFactory extends PowderFactory {
        @Override
        public Powder create() {
            return new LsfPowder();
        }
    }

     桂林米粉(具体工厂子类):

    package com.wbg.FactoryMode;
    
    public class createGlFactory extends PowderFactory{
        @Override
        public Powder create() {
            return new GlPowder();
        }
    }

     使用:

    package com.wbg.FactoryMode;
    
    public class Customer {
        public static void main(String[] args) {
           PowderFactory factory=new createGlFactory();
           Powder powder=factory.create();
           powder.desc();
        }
    }

    普通工厂与简单工厂模式的区别:

    可以看出,普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象。

    工厂方法使一个产品类的实例化延迟到其具体工厂子类.

    工厂方法的好处就是更拥抱变化。当需求变化,只需要增删相应的类,不需要修改已有的类。

    简单工厂需要修改工厂类的create()方法,多方法静态工厂模式需要增加一个静态方法。

    缺点:

    引入抽象工厂层后,每次新增一个具体产品类,也要同时新增一个具体工厂类!

    抽象工厂

    以上介绍的工厂都是单产品系的。抽象工厂是多产品系 。

    每个粉店(工厂)不仅仅卖粉,还提供饮料卖。 
    提供饮料卖,饮料是产品,先抽象一个产品类,饮料:

    public abstract class IDrinks {
        /**
         * 描述每种饮料多少钱
         */
        public abstract void prices();
    }

    可乐:

    public class ColaDrinks extends IDrinks {
        @Override
        public void prices() {
            System.out.println("可乐1块钱");
        }
    }

    水:

    public class WaterDrinks extends IDrinks {
        @Override
        public void prices() {
            System.out.println("太辣了,我要和免费水");
        }
    }

    抽象粉店(抽象工厂类):

    public abstract class AbstractFoodFactory {
        /**
         * 生产面条
         *
         * @return
         */
        public abstract Powder createPowder();
    
        /**
         * 生产饮料
         */
        public abstract IDrinks createDrinks();
    }

    柳州螺蛳粉(具体工厂类):

    public class LsflmFoodFactory extends AbstractFoodFactory {
        @Override
        public Powder createPowder() {
            return new LsfPowder();//螺蛳粉
        }
    
        @Override
        public IDrinks createDrinks() {
            return new WaterDrinks();//卖水
        }
    }

    酒店(具体工厂类):

    public class hodelFoodFactory extends AbstractFoodFactory {
        @Override
        public Powder createPowder() {
            return new GlPowder();//桂林米粉很好吃,酒店都有了
        }
    
        @Override
        public IDrinks createDrinks() {
            return new ColaDrinks();//卖可乐
        }
    }

    使用:

     AbstractFoodFactory abstractFoodFactory1 = new hodelFoodFactory();
            abstractFoodFactory1.createDrinks().prices();
            abstractFoodFactory1.createPowder().desc();
    
    
            AbstractFoodFactory abstractFoodFactory2 = new LsflmFoodFactory();
            abstractFoodFactory2.createDrinks().prices();
            abstractFoodFactory2.createPowder().desc()

    缺点

    将工厂也抽象后,有个显著问题,就是类爆炸了。而且每次拓展新产品种类,例如不仅卖吃卖喝,我还想卖其他,这需要修改抽象工厂类,因此所有的具体工厂子类,都被牵连,需要同步被修改。

    demo:https://github.com/weibanggang/Factorydemo

  • 相关阅读:
    es6 常用方法
    vue HTTP 请求(vue-resource)
    vue 常用语法糖
    js中slice,SubString和SubStr的区别
    浅谈JavaScript中forEach与each
    vue 新版本 webpack 代理 跨域设置
    js 动态添加class封装(es6语法)
    jsonp promise 封装
    location.origin兼容IE
    给zTree的treeNode添加class
  • 原文地址:https://www.cnblogs.com/weibanggang/p/10094790.html
Copyright © 2011-2022 走看看