• 设计模式--工厂模式分析总结


    先来一个生动的例子:

      大众汽车的MQB平台是现在非常出名的横置发动机模块化生产平台,从这个平台上出生了许多的广为人知的汽车型号,如奥迪TT、大众Polo、高尔夫等等。抽象化思考,这些汽车都出自一个生产平台,而不是每辆车都单独占有一个平台,那么问题来了,如何让一个平台生产出多个型号的汽车呢?

      我们以上述三种车型为例,先定义出三种车的类

    public class AudiTT {
        public void run() {
            System.out.println("AudiTT run...");
        }
    }
    
    public class Polo {
        public void run() {
            System.out.println("Polo run...");
        }
    }
    
    public class Golf {
        public void run() {
            System.out.println("Golf run...");
        }
    }

      如何让平台生产三种型号的车型呢?有同学就会提出这样的做法,让平台实现每个型号的生产方法不就行了,于是乎有了下面的代码

    public class Factory {
        public AudiTT produceAudiTT() {
            return new AudiTT();
        }
        public Polo producePolo() {
            return new Polo();
        }
        public Golf produceGolf() {
            return new Golf();
        }
    }

      写个场景类测试一下

    public class Test {
        public static void main(String[] args) {
            Factory factory = new Factory();
            AudiTT audiTT = factory.produceAudiTT();
            Polo polo = factory.producePolo();
            audiTT.run();
            polo.run();
        }
    }

      输出结果

    AudiTT run...
    Polo run...

      这么做看起来似乎是可行的,但是我们注意到,这个工厂类实际上没有一点作用,相当于我们自己new了一个具体的汽车对象,在接收工厂生产出的对象时,也不能用统一的类去接收,且我们每增加一个汽车类,就需要修改工厂类,工厂类和汽车类之间耦合性极强,增加出错风险,代码的复用性也不高,这是不符合设计原则的。

      为了增强类间解耦合,我们引入抽象类,定义产品的公共行为,此例中就是run()方法,我们定义Car类为汽车类的公共父类

    public abstract class Car {
        public abstract void run();
    }

      此时,三个汽车类相应继承Car类,并重写run()方法

    public class AudiTT extends Car{
        @Override
        public void run() {
            System.out.println("AudiTT run...");
        }
    }
    
    public class Polo extends Car {
        @Override
        public void run() {
            System.out.println("Polo run...");
        }
    }
    
    public class Golf extends Car{
        @Override
        public void run() {
            System.out.println("Golf run...");
        }
    }

      此时,工厂类却可以发生重大变化,我们引入抽象工厂类

    public abstract class AbsFactory {
        public abstract <T extends Car> T produce(Class<T> clazz);
    }

      引入具体工厂类继承抽象工厂,重写生产方法

    public class Factory extends AbsFactory{
    
        @Override
        public <T extends Car> T produce(Class<T> clazz) {
            Car car = null;
            try {
                car = (Car)Class.forName(clazz.getName()).getDeclaredConstructor().newInstance();
            }catch (Exception e) {
                e.printStackTrace();
            }
            return (T)car;
        }
    }

      写一个场景类进行实验

    public class Test {
        public static void main(String[] args) {
            AbsFactory factory = new Factory();
            Car audiTT = factory.produce(AudiTT.class);
            Car polo = factory.produce(Polo.class);
            audiTT.run();
            polo.run();
        }
    }

      输出结果:

    AudiTT run...
    Polo run...

      现在,我们每增加一个汽车类,再也不用修改工厂类,只要传入具体的类对象信息,工厂类都可以按要求生产对应的汽车对象,实现了汽车类和工厂类解耦合,增加了代码复用度。

      我们注意到,在测试类中,我们都是用父类对象去接收子类对象,这在Java中是可行的,利用了Java中子类的向上转型,实现接收变量的统一化,还有就是具体工厂类中,利用了Java的反射功能。

      还可以在抽象产品类中加入所有具体产品类的共有属性和方法,进行扩展,同时,抽象工厂类也可以有多个不同的子类,以实现多个生产不同产品,比如汽车工厂、电脑工厂等等不同性质的产品工厂,进行扩展。

    优点:

      使一个类的实例化延迟到子类,实现类间解耦,屏蔽产品类,增强代码复用度。

    具体案例

      如果使用JDBC链接数据库,数据库从MySQL变换到Oracle,唯一需要做的就是改变驱动名称,其他都不需要修改  

    通用模版

      我们很容易从上述代码中提取出通用模版

      抽象产品类

    public abstract class AbsProduct {
        //产品类的公共方法
        public void method1() {
            
        }
        //具体产品类的具体方法,留给子类具体实现
        public abstract void method2();
    }

      具体产品类

    public class ConcreteProduct extends AbsProduct {
        @Override
        public void method2() {
            
        }
    }

      具体产品类可以有多个,越多越能体现工厂模式的优点

      抽象工厂类

    public abstract class AbsFactory {
        public abstract <T extends AbsProduct> T produce(Class<T> c);
    }

      具体工厂类

    public class ConcreteFactory extends AbsFactory {
        @Override
        public <T extends AbsProduct> T produce(Class<T> c) {
            AbsProduct product = null;
            try {
                product = (AbsProduct) Class.forName(c.getName()).getDeclaredConstructor().newInstance();
            }catch (Exception e) {
                e.printStackTrace();
            }
            return (T) product;
        }
    }

      这只是普通工厂模式的简要介绍,更工厂的抽象工厂模式,留作下一篇总结

      

  • 相关阅读:
    C# 事务之SqlTransaction
    java获取字符串格式日期向前或向后n天的日期
    java中保留几位小数
    第一个androidAPP项目总结—ListView的上拉和下拉
    java中static作用详解
    第一个androidAPP项目总结—数据请求
    获取控件的高和宽
    Android学习笔记:如何设置ImageView中图片的显示方式
    TextView过长显示省略号, TextView文字中间加横线
    android中控件的使用
  • 原文地址:https://www.cnblogs.com/dwwzone/p/13060928.html
Copyright © 2020-2023  润新知