软件设计模式——工厂设计模式

工厂模式(Factory Pattern)是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模 式,它提供了一种创建对象的最佳方式。

工厂模式分为:

  1. 简单工厂模式
  2. 工厂方法模式
  3. 抽象工厂模式

首先, 工厂模式是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只是调用B的方法,而至于B的实例化,就交给工厂类。

其次, 工厂模式可以降低代码重复。如果创建对象B的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。我们可以这些创建对象B的代码放到工厂里统一管理。既减少了重复代码,也方便以后对B的创建过程的修改维护。(当然,我个人觉得也可以把这些创建过程的代码放到类的构造函数里,同样可以降低重复率,而且构造函数本身的作用也是初始化对象。不过,这样也会导致构造函数过于复杂,做的事太多,不符合java 的设计原则。)

由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。同理,想把所有调用B的地方改成B的子类B1,只需要在对应生产B的工厂中或者工厂的方法中修改其生产的对象为B1即可,而不需要找到所有的new B()改为new B1()。

另外, 因为工厂管理了对象的创建逻辑,使用者并不需要知道具体的创建过程,只管使用即可,减少了使用者因为创建逻辑导致的错误。

举个例子:

一个数据库工厂:可以返回一个数据库实例,可以是mysql,oracle等。

这个工厂就可以把数据库连接需要的用户名,地址,密码等封装好,直接返回对应的数据库对象就好。不需要调用者自己初始化,减少了写错密码等等这些错误。调用者只负责使用,不需要管怎么去创建、初始化对象。

还有,如果一个类有多个构造方法(构造的重写),我们也可以将它抽出来,放到工厂中,一个构造方法对应一个工厂方法并命名一个友好的名字,这样我们就不再只是根据参数的不同来判断,而是可以根据工厂的方法名来直观判断将要创建的对象的特点。这对于使用者来说,体验比较好。

工厂模式适用的一些场景(不仅限于以下场景):

1. 对象的创建过程/实例化准备工作很复杂,需要初始化很多参数、查询数据库等。

2.类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。


在没有使用工厂模式下的普通场景

(产品)代码:

package oopdemo01.Design_pattern.factory.simple.A_normal;

public interface Car {
    void name();
}

(产品种类)代码:

package oopdemo01.Design_pattern.factory.simple.A_normal;

public class Tesla implements Car {
    @Override
    public void name() {
        System.out.println("特斯拉");
    }
}

(产品种类)代码:

package oopdemo01.Design_pattern.factory.simple.A_normal;

public class WuLing implements Car {
    @Override
    public void name() {
        System.out.println("五菱宏光");
    }
}

(消费者)代码:

package oopdemo01.Design_pattern.factory.simple.A_normal;

// 普通模式下消费者
public class Consumer {
    public static void main(String[] args) {
        // 接口,所有的实现类
        Car car1 = new WuLing();
        Car car2 = new Tesla();

        car1.name();
        car2.name();
    }
}

由消费者代码可知,当你需要一个产品对象时,你只能通过new来获取。


一、简单工厂模式

 在普通场景下,新增了一个车工厂的代码。

(车工厂)代码:

package oopdemo01.Design_pattern.factory.simple.B_easy_factory;

// 简单工厂模式(弊端,新增一个车类,还需修改此类的代码)
public class CarFactory {
    public static Car getCar(String car) {
        if (car.equals("五菱")) {
            return new WuLing();
        } else if (car.equals("特斯拉")) {
            return new Tesla();
        } else {
            return null;
        }
    }
}

(此时的消费者)代码:

package oopdemo01.Design_pattern.factory.simple.B_easy_factory;

// 使用工厂模式下的消费者
public class Consumer {
    public static void main(String[] args) {
        // 使用工厂模式创建对象
        Car car1 = CarFactory.getCar("五菱");
        Car car2 = CarFactory.getCar("特斯拉");

        car1.name();
        car2.name();
    }
}

通过消费者代码可发现,此时需要一个产品对象时,只需要通过车工厂的方法即可。


二、工厂方法模式

为了更加符合设计原则,即开放-封闭原则(新增代码不修改原有代码),出现了工厂方法模式。

将原来的车工厂变成一种条件(接口)而不是原来的实现方法。

 车工厂(变成了接口)代码:

package oopdemo01.Design_pattern.factory.simple.C_method_factory;

// 工厂方法模式
public interface CarFactory {
    Car getCar();
}

(特斯拉汽车工厂)代码:

package oopdemo01.Design_pattern.factory.simple.C_method_factory;

public class TeslaFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new Tesla();
    }
}

(五菱宏光汽车工厂)代码:

package oopdemo01.Design_pattern.factory.simple.C_method_factory;

public class WuLingFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new WuLing();
    }
}

(消费者)代码:

package oopdemo01.Design_pattern.factory.simple.C_method_factory;


// 使用工厂方法模式下的消费者
public class Consumer {
    public static void main(String[] args) {
        Car car1 = new WuLingFactory().getCar();
        Car car2 = new TeslaFactory().getCar();
        car1.name();
        car2.name();

        Car car3 = new MoBaiFactory().getCar();
        car3.name();
    }
}

由消费者代码可知,车工厂分成了不同的种类的品牌工厂,新增汽车时,只需新增一个Car类和对应该Car类的工厂即可(用来new此Car对象)。


但是:

结构复杂度 代码复杂度 编程复杂度 管理复杂度

均是简单工厂模式更优

根据设计原则:工厂方法模式

根据实际业务:简单工厂模式


三、抽象工厂模式(工厂的工厂)

定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口。

需先来了解下产品等级和产品族,相同的产品等级就是相同的产品,像美的冰箱、格力冰箱、海尔冰箱,都是冰箱,它们的产品等级都相同,虽然厂家不同。美的冰箱、美的空调和美电风扇,他们都来自同一家厂商美的,他们的产品族相同。

抽象工厂强调了一系列相关产品对象(属于同一个产品族)的创建过程,它和工厂方法模式的侧重点不同,工厂方法模式更加侧重于同一产品等级,而抽象工厂模式侧重的是同一产品族。简单说就是一个工厂中生产的一系列对象都是同一个产品族的。

(手机产品接口)代码:

package oopdemo01.Design_pattern.factory.simple.D_abstract_factory;

// 手机产品接口
public interface IphoneProduct {
    void start();

    void shutdown();

    void callup();

    void sendsMS();
}

(路由器产品接口)代码:

package oopdemo01.Design_pattern.factory.simple.D_abstract_factory;

// 路由器产品接口
public interface RouterProduct {
    void start();

    void shutdown();

    void openWife();

    void setting();
}

(抽象工厂接口)代码:

package oopdemo01.Design_pattern.factory.simple.D_abstract_factory;

// 抽象产品工厂
public interface ProductFactory {
    // 生产手机
    IphoneProduct iphoneProduct();

    // 生产路由器
    RouterProduct routerProduct();
}

(华为手机)代码:

package oopdemo01.Design_pattern.factory.simple.D_abstract_factory;

public class HuaWeiPhone implements IphoneProduct {
    @Override
    public void start() {
        System.out.println("开启华为手机");
    }

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

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

    @Override
    public void sendsMS() {
        System.out.println("华为发短信");
    }
}

(华为路由器)代码:

package oopdemo01.Design_pattern.factory.simple.D_abstract_factory;

public class HuaWeiRouter implements RouterProduct {
    @Override
    public void start() {
        System.out.println("启动华为路由器");
    }

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

    @Override
    public void openWife() {
        System.out.println("打开华为wife");
    }

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

(华为产品工厂)代码:

package oopdemo01.Design_pattern.factory.simple.D_abstract_factory;

public class HuaWeiFactory implements ProductFactory {
    @Override
    public IphoneProduct iphoneProduct() {
        return new HuaWeiPhone();
    }

    @Override
    public RouterProduct routerProduct() {
        return new HuaWeiRouter();
    }
}

(消费者)代码:

package oopdemo01.Design_pattern.factory.simple.D_abstract_factory;

public class Client {
    public static void main(String[] args) {
        System.out.println("=========小米系列产品=========");
        // 小米工厂
        XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();
        IphoneProduct iphoneProduct = xiaoMiFactory.iphoneProduct();

        iphoneProduct.callup();
        iphoneProduct.sendsMS();

        RouterProduct routerProduct = xiaoMiFactory.routerProduct();
        routerProduct.openWife();

        System.out.println("=========华为系列产品=========");
        // 华为工厂
        HuaWeiFactory huaWeiFactory = new HuaWeiFactory();

        iphoneProduct = huaWeiFactory.iphoneProduct();
        iphoneProduct.callup();
        iphoneProduct.sendsMS();

        routerProduct = huaWeiFactory.routerProduct();
        routerProduct.openWife();
    }
}

抽象工厂模式:工厂的工厂。


总结: 通过以上三个案例,对比分析明确了三种工厂模式实现的方式,也对比分析了各个工厂模式的优点。但 是切记,实际开发过程中,不要盲目的使用,一定要结合具体的业务,实际分析后才去使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王雀跃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值