设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)

文章目录

  • 工厂模式
    • 1、不使用工厂
    • 2、简单(静态)工厂模式
    • 3、工厂方法模式
    • 4、抽象工厂模式
      • 4.1、案例
  • 工厂模式总结

工厂模式

  • 工厂模式的作用:实现了创建者和调用者的分离
  • 核心本质:
    • 实例化对象不使用new,用工厂方法代替
    • 将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦
  • 详细分类:
    • 简单(静态)工厂模式:用来生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有代码)
    • 工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品)
    • 抽象工厂模式:围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
  • 满足OOP七大原则中的三个:
    • 开闭原则: 一个软件的实体应当对扩展开放,对修改关闭
    • 依赖倒转原则: 要针对接口编程,不要针对实现编程
    • 迪米特法则:只与你直接的朋友通信,而避免和陌生人通信
  • 下面举一个消费者买车的例子

1、不使用工厂

不使用工厂,消费者去买车就要自己去new一辆车,这实际上就是消费者自己去造了一辆车,不符合买车的需求

//车的总接口
package com.wlw.factory;

public interface Car {
     void name();
}
//车的实现类
package com.wlw.factory;

public class Wuling implements Car {
    @Override
    public void name() {
        System.out.println("五菱宏光");
    }
}
//车的实现类
package com.wlw.factory;

public class Tasla implements Car {
    @Override
    public void name() {
        System.out.println("特斯拉");
    }
}
package com.wlw.factory;

public class Consumer {
    public static void main(String[] args) {
        Car car1 = new Wuling();
        Car car2 = new Tasla();

        car1.name();//五菱宏光
        car2.name();//特斯拉
    }
}

2、简单(静态)工厂模式

  • 消费者自己不去new车(不用关心车怎么实现的细节),而是通过工厂生产车,减少硬编码。

  • 大多数情况下用的都是简单工厂模式,这种模式仍有不足

  • 缺点:如以下代码,在简单工厂中已经可以创建五菱宏光和特斯拉两种车,但是如果再增加一辆车,则会修改CarFactory.java的getCar方法,违反了开闭原则,我们应该扩展,不应该去修改一个方法。

  • 写一个生产车的工厂,我们只需要传入车的名字,就可以得到这辆车,实现细节交给工厂来处理

设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)_第1张图片

package com.wlw.factory;
//静态(简单)工厂模式
public class CarFactory {
    public static Car getCar(String name){
        if(name == "五菱"){
            return new Wuling();
        }else if(name == "特斯拉"){
            return new Tasla();
        }else {
            return null;
        }
    }
}
  • 测试
package com.wlw.factory;

public class Consumer {
    public static void main(String[] args) {
        //1.不使用工厂,消费者自己去new一辆车,实现细节要自己做
        //Car car1 = new Wuling();
        //Car car2 = new Tasla();

        //2.使用简单工厂来生产车,实现细节交给工厂
        Car car1 = CarFactory.getCar("五菱");
        Car car2 = CarFactory.getCar("特斯拉");

        car1.name();//五菱宏光
        car2.name();//特斯拉
    }
}

3、工厂方法模式

  • 我们新建一个CarFactory的接口,然后为每种Car都建一个Factory类。这样就可以使得每次新加入一种车时,只为这种车建立一个对应的工厂就行,不会影响到原来的代码。
  • 优点:下次加入一种大众车,(扩展)只需要新建一个 DazhongFactory 就行,不会影响到别的工厂。
  • 缺点:代码量加大,管理复杂,结构复杂,编程复杂,实际业务一般使用简单工厂模式
  • 根据设计原则,选择工厂方法模式;根据实际业务,选择简单工厂模式
  • 总结:不一定要符合设计原则,要根据实际情况加以分析取舍

设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)_第2张图片

package com.wlw.factory.factorymethod;
//工厂方法模式
public interface CarFactory {
    Car getCar();
}

package com.wlw.factory.factorymethod;

public class WulingFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new Wuling();
    }
}

package com.wlw.factory.factorymethod;

public class TaslaFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new Tasla();
    }
}

package com.wlw.factory.factorymethod;

public class Consumer {
    public static void main(String[] args) {
        //1.不使用工厂,消费者自己去new一辆车,实现细节要自己做
        //Car car1 = new Wuling();
        //Car car2 = new Tasla();

        //2.使用简单工厂来生产车,实现细节交给工厂
        //Car car1 = CarFactory.getCar("五菱");
        //Car car2 = CarFactory.getCar("特斯拉");

        //3.方法工厂,为每种Car都建一个Factory类
        Car car1 = new WulingFactory().getCar();
        Car car2 = new TaslaFactory().getCar();

        car1.name();//五菱宏光
        car2.name();//特斯拉
    }
}

4、抽象工厂模式

  • 定义:抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类
  • 适用场景:
    • 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
    • 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
    • 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现
  • 优点:
    • 具体产品在应用层的代码隔离,无需关心创建的细节
    • 将一个系列的产品统一到一起创建
  • 缺点:
    • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难;
    • 增加了系统的抽象性和理解难度

设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)_第3张图片

4.1、案例

设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)_第4张图片

  • 可以看到产品分支与工厂分支是独立开来的,产品分支分为多个产品接口,一个产品接口又可以有多个实现类。而工厂分支中的大工厂指定了可以生产哪些产品,其实现类(华为厂商或小米厂商)可以直接new出产品并返回。在测试类中需要某个厂商的某个产品时,直接new出需要的厂商并调用其获取产品的方法。

  • 代码结构

设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)_第5张图片

package com.wlw.factory.abstract1;
//抽象产品工厂,用来创建具体的产品工厂
public interface ProductFactory {

    //手机工厂,用来生产手机
    PhoneProduct  phoneProduct();

    //路由器工厂,用来生产路由器
    RouterProduct routerProduct();
}

package com.wlw.factory.abstract1;
//手机产品接口(工厂)
public interface PhoneProduct {
    void start();
    void shutdown();
    void call();
    void sendmsg();
}

package com.wlw.factory.abstract1;
//路由器产品接口(工厂)
public interface RouterProduct {
    void start();
    void shutdown();
    void openwifi();
    void setting();
}

package com.wlw.factory.abstract1;
//具体的手机产品
public class XiaomiPhone implements PhoneProduct {
    @Override
    public void start() {
        System.out.println("小米手机开机");
    }

    @Override
    public void shutdown() {
        System.out.println("小米手机关机");
    }

    @Override
    public void call() {
        System.out.println("小米手机打电话");
    }

    @Override
    public void sendmsg() {
        System.out.println("小米手机发信息");
    }
}

package com.wlw.factory.abstract1;
//具体的手机产品
public class HuaweiPhone implements PhoneProduct {
    @Override
    public void start() {
        System.out.println("华为手机开机");
    }

    @Override
    public void shutdown() {
        System.out.println("华为手机关机");
    }

    @Override
    public void call() {
        System.out.println("华为手机打电话");
    }

    @Override
    public void sendmsg() {
        System.out.println("华为手机发信息");
    }
}

package com.wlw.factory.abstract1;
//具体的路由器产品
public class XiaomiRouter implements RouterProduct{

    @Override
    public void start() {
        System.out.println("小米路由器开机");
    }

    @Override
    public void shutdown() {
        System.out.println("小米路由器关机");
    }

    @Override
    public void openwifi() {
        System.out.println("小米路由器打开wifi");
    }

    @Override
    public void setting() {
        System.out.println("小米路由器设置");
    }
}

package com.wlw.factory.abstract1;
//具体的路由器产品
public class HuaweiRouter implements RouterProduct{
    @Override
    public void start() {
        System.out.println("华为路由器开机");
    }

    @Override
    public void shutdown() {
        System.out.println("华为路由器关机");
    }

    @Override
    public void openwifi() {
        System.out.println("华为路由器打开wifi");
    }

    @Override
    public void setting() {
        System.out.println("华为路由器设置");
    }
}

package com.wlw.factory.abstract1;
//小米工厂来生产小米系列的产品
public class XiaomiProductFactory implements ProductFactory {

    //小米手机
    @Override
    public PhoneProduct phoneProduct() {
        return new XiaomiPhone();
    }

    //小米路由器
    @Override
    public RouterProduct routerProduct() {
        return new XiaomiRouter();
    }
}

package com.wlw.factory.abstract1;
//华为工厂来生产华为系列的产品
public class HuaweiProductFactory implements ProductFactory {

    //华为手机
    @Override
    public PhoneProduct phoneProduct() {
        return new HuaweiPhone();
    }

    //华为路由器
    @Override
    public RouterProduct routerProduct() {
        return new HuaweiRouter();
    }
}

package com.wlw.factory.abstract1;

public class TestClient {
    public static void main(String[] args) {

        System.out.println("===================小米系列=================");
        //用小米工厂来创建一个手机工厂,在手机工厂里生产小米手机
        XiaomiProductFactory xiaomiProductFactory = new XiaomiProductFactory();
        PhoneProduct xiaomiphone = xiaomiProductFactory.phoneProduct();
        xiaomiphone.start();

        //用小米工厂来创建一个路由器工厂,在路由器工厂里生产小米路由器
        RouterProduct xiaomirouter = xiaomiProductFactory.routerProduct();
        xiaomirouter.start();

        System.out.println("===================华为系列=================");
        //用华为工厂来创建一个手机工厂,在手机工厂里生产华为手机
        HuaweiProductFactory huaweiProductFactory = new HuaweiProductFactory();
        PhoneProduct huaweiPhone = huaweiProductFactory.phoneProduct();
        huaweiPhone.start();
    }
}
/*
===================小米系列=================
小米手机开机
小米路由器开机
===================华为系列=================
华为手机开机

*/
  • 该设计模式优缺点:
    • 优点:
      • 厂商是具有可扩展性的,可有多个厂商去生产手机与路由器
      • 厂商可以将一个系列的产品放到一起创建
      • 调用者无需关心产品的创建过程,只需要获取工厂即可
    • 缺点:
      • 如果要生产更多的产品就必须要改动大工厂,厂商也需改动,产品集合被固定了

工厂模式总结

  • 小结:

    • 简单工厂模式(静态工厂模式)
      • 虽然某种程度上不符合设计原则,但实际使用最多!
    • 工厂方法模式
      • 不修改已有类的前提下,通过增加新的工厂类实现扩展。
    • 抽象工厂模式
      • 不可以增加产品,可以增加产品族!
  • 应用场景:

    • JDK中Calendar的getlInstance方法
    • JDBC中的Connection对象的获取
    • Spring中IOC容器创建管理bean对象反射中Class对象的newInstance方法

你可能感兴趣的:(Java设计模式,抽象工厂模式,工厂方法模式,简单工厂)