设计模式系列1 工厂模式

Posted wenteryan

tags:

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

工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

使用场景

1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。

五种工厂模式

1)简单工厂(静态)

案例:生产车辆

抽象一个汽车基类,或者是接口

public abstract class CarPrototype 
    /**
     * 生产汽车
     */
    public abstract void produce();

生产奥迪汽车(具体的产品类)

public class AodeCar extends CarPrototype 

    @Override
    public void produce() 
        // TODO Auto-generated method stub
        System.out.println("生产一辆奥迪汽车。。。。。。。。。。。。");
    

生产宝马汽车(具体的产品类)

public class BaomaCar extends CarPrototype 

    @Override
    public void produce() 
        // TODO Auto-generated method stub
        System.out.println("生产一辆宝马汽车。。。。。。。。。。。。");
    

生产红旗汽车(具体的产品类)

public class HongqiCar extends CarPrototype 

    @Override
    public void produce() 
        // TODO Auto-generated method stub
        System.out.println("生产一辆红旗汽车。。。。。。。。。。。。");
    

汽车工厂(简单工厂类)

public class SimpleCarFactory 

    public static CarPrototype createCar(String type) 
        switch(type) 
            case "baoma":
                return new BaomaCar();
            case "aode":
                return new AodeCar();
            case "hongqi":
                return new HongqiCar();
            default:
                throw new BaseException("工厂类无法匹配汽车,没法生产。。。。。");
        

    

测试生产汽车

public class TestCarFactory 
    public static void main(String[] args) 
        CarPrototype carPrototype = new SimpleCarFactory().createCar("baoma");
        carPrototype.produce();
    

结果

生产一辆宝马汽车。。。。。。。。。。。。


特点
1 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。
2 create()方法通常是静态的,所以也称之为静态工厂。
缺点
1 扩展性差(我想增加一种汽车,除了新增一个汽车产品类,还需要修改工厂类方法)
2 不同的产品需要不同额外参数的时候 不支持。

2)简单工厂(反射)

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

public class ReflectionCarFactory 

    public static <T extends CarPrototype> T createCar(Class<T> prototype) 
        T result = null;
        try 
            result = (T)Class.forName(prototype.getName()).newInstance();
         catch (Exception e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
        return result;
    

测试简单工厂(反射)

public class TestCarFactory 
    public static void main(String[] args) 

        // 简单工厂(静态)
        /*CarPrototype carPrototype = new SimpleCarFactory().createCar("baoma");
        carPrototype.produce();*/

        // 简单工厂(反射)
        CarPrototype carPrototype =  ReflectionCarFactory.createCar(AodeCar.class);
        carPrototype.produce();
    

结果

生产一辆奥迪汽车。。。。。。。。。。。。


特点
1 它也是一个具体的类,非接口 抽象类。但它的create()方法,是利用反射机制生成对象返回,好处是增加一种产品时,不需要修改create()的代码。
缺点
这种写法粗看牛逼,细想之下,不谈reflection的效率还有以下问题:
1 个人觉得不好,因为Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂。
2 不同的产品需要不同额外参数的时候 不支持。

3)多方法工厂(常用)

不同的产品需要不同额外参数的时候 不支持。
而且如果使用时传递的type、Class出错,将不能得到正确的对象,容错率不高。
而多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。

工厂如下

public class ManyWayCarFactory 
    /**
     * 生产奥迪汽车
     * @return
     */
    public static CarPrototype createAodeCar() 
        return new AodeCar();
    
    /**
     * 生产宝马汽车
     * @return
     */
    public static CarPrototype createBaomaCar() 
        return new BaomaCar();
    
    /**
     * 生产红旗汽车
     * @return
     */
    public static CarPrototype createHongqiCar() 
        return new HongqiCar();
    

测试多方法工厂(常用)

public class TestCarFactory 
    public static void main(String[] args) 

        // 简单工厂(静态)
        /*CarPrototype carPrototype = new SimpleCarFactory().createCar("baoma");
        carPrototype.produce();*/

        // 简单工厂(反射)
        /*CarPrototype carPrototype =  ReflectionCarFactory.createCar(AodeCar.class);
        carPrototype.produce();*/

        // 多方法静态工厂(模仿Executor类)
        CarPrototype carPrototype =  new ManyWayCarFactory().createHongqiCar();
        carPrototype.produce();
    

结果

生产一辆红旗汽车。。。。。。。。。。。。
4)普通工厂

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

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

public abstract class CarFactory 
    public abstract CarPrototype create();

生产奥迪工厂(具体工厂子类)

public class AodeFactory extends CarFactory 

    public CarPrototype create() 
        // TODO Auto-generated method stub
        return new AodeCar();
    

生产宝马工厂(具体工厂子类)

public class BaomaFactory extends CarFactory 

    public CarPrototype create() 
        // TODO Auto-generated method stub
        return new BaomaCar();
    

生产红旗工厂(具体工厂子类)

public class HongqiFactory extends CarFactory 

    public CarPrototype create() 
        // TODO Auto-generated method stub
        return new HongqiCar();
    

测试普通工厂

public class TestCarFactory 
    public static void main(String[] args) 

        // 简单工厂(静态)
        /*CarPrototype carPrototype = new SimpleCarFactory().createCar("baoma");
        carPrototype.produce();*/

        // 简单工厂(反射)
        /*CarPrototype carPrototype =  ReflectionCarFactory.createCar(AodeCar.class);
        carPrototype.produce();*/

        // 多方法静态工厂(模仿Executor类)
        /*CarPrototype carPrototype =  new ManyWayCarFactory().createHongqiCar();
        carPrototype.produce();*/

        // 普通工厂
        CarPrototype carPrototype =  new BaomaFactory().create();
        carPrototype.produce();
    

结果

生产一辆宝马汽车。。。。。。。。。。。。

普通工厂与简单工厂模式的区别:
可以看出,普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象。
工厂方法使一个产品类的实例化延迟到其具体工厂子类。
工厂方法的好处就是更拥抱变化。当需求变化,只需要增删相应的类,不需要修改已有的类。
而简单工厂需要修改工厂类的create()方法,多方法静态工厂模式需要增加一个静态方法。
缺点:
引入抽象工厂层后,每次新增一个具体产品类,也要同时新增一个具体工厂类,所以我更青睐 多方法静态工厂。

5)抽象工厂

以上介绍的工厂都是单产品系的。抽象工厂是多产品系 (貌似也有产品家族的说法)。
举个例子来说,每个店(工厂)不仅仅生产汽车,还生产零件。

生产零件,零件是产品,先抽象一个产品类,零件:

public abstract class ComponentsPrototype 
    /**
     * 生产零件
     */
    public abstract void produce();

生产车门

public class CarDoorComponents extends ComponentsPrototype 

    @Override
    public void produce() 
        // TODO Auto-generated method stub
        System.out.println("生产车门-------------");
    

生产发动机

public class EngineComponents extends ComponentsPrototype 

    @Override
    public void produce() 
        // TODO Auto-generated method stub
        System.out.println("生产发动机-------------");
    

抽象汽车工厂(抽象工厂类)

public abstract class AbstractCarFactory 
    /**
     * 生产汽车
     * @return
     */
    public abstract CarPrototype createCar();
    /**
     * 生产零件
     * @return
     */
    public abstract ComponentsPrototype createComponents();

测试抽象工厂

public class TestCarFactory 
    public static void main(String[] args) 

        // 简单工厂(静态)
        /*CarPrototype carPrototype = new SimpleCarFactory().createCar("baoma");
        carPrototype.produce();*/

        // 简单工厂(反射)
        /*CarPrototype carPrototype =  ReflectionCarFactory.createCar(AodeCar.class);
        carPrototype.produce();*/

        // 多方法静态工厂(模仿Executor类)
        /*CarPrototype carPrototype =  new ManyWayCarFactory().createHongqiCar();
        carPrototype.produce();*/

        // 普通工厂
        /*CarPrototype carPrototype =  new BaomaFactory().create();
        carPrototype.produce();*/

        // 抽象工厂
        CarPrototype carPrototype =  new ChinaCarFactory().createCar();
        carPrototype.produce();
        ComponentsPrototype componentsPrototype =  new ChinaCarFactory().createComponents();
        componentsPrototype.produce();
    

结果

生产一辆宝马汽车。。。。。。。。。。。。
生产发动机-------------

以上是关于设计模式系列1 工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式从青铜到王者第七篇:创建型模式之抽象工厂模式(Abstract Factory)

设计模式系列-02-工厂方法

抽象工厂模式

抽象工厂模式

抽象工厂模式和原型模式之间的区别?

深入理解设计模式---系列目录