设计模式-工厂模式

工厂模式介绍

它提供了了⼀种创建对象的最佳方式,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象

工厂模式的好处:

  • 解耦:分离职责,把复杂的对象的创建和使用的过程分开
  • 复用代码降低维护成本:如果对象创建复杂且多处需用到,如果每处都进行编写,则很多重复代码,如果业务逻辑发生了改变,需要四处修改;使用工厂模式统一创建,则只需要修改工厂类即可,降低维护成本

工厂模式三种不同实现方式

  1. 简单工厂模式:通过传入相关的类型来返回相应的类,这种方式比较单一,可扩展性相对较差
  2. 工厂方法模式:通过实现类实现相应的方法来决定相应的返回结果,这种方式的可扩展性比较强
  3. 抽象工厂模式:基于上述两种模式的拓展,且支持细化产品

1. 简单工厂模式

简单工厂模式又称静态工厂,可以根据参数的不同返回不同类的实例,专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类。
由于工厂方法是静态方法,可通过类名直接调用,而且只需要传入简单的参数即可

  • 核心组成

    • Factory:工厂类,简单工厂模式的核心,它负责实现创建所有实例的内部逻辑
    • IProduct:抽象产品类,简单工厂模式所创建的所有对象的父类,描述所有实例所共有的公共接口
    • Product: 具体产品类,是简单工厂模式的创建目标
  • 实现步骤

    • 创建抽象产品类,里面有产品的抽象方法,由具体的产品类去实现
    • 创建具体产品类,继承了他们的父类,并实现具体方法
    • 创建工厂类,提供了一个静态方法createXXX用来生产产品,只需要传入你想要的产品名称
  • 优点

    • 将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来相对容易
  • 缺点

    • 工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背(开闭原则即对外开放,对修改关闭,程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果)
    • 将会增加系统中类的个数,在一定程度上增加了系统的复杂度和理解难度,不利于系统的扩展和维护,创建简单对象就不用模式

电商支付案例-简单工厂模式的实践DEMO案例代码

public interface Pay {

    // 统一下单抽象方法
    void unifiedorder();
}


public class AliPay implements Pay {
    @Override
    public void unifiedorder() {
        System.out.println("支付宝支付---统一下单逻辑");
    }
}

public class WeichatPay implements Pay {
    @Override
    public void unifiedorder() {
        System.out.println("微信支付---统一下单逻辑");
    }
}

public class SimplePayFactory {
    /**
     * 根据参数返回对应的支付对象
     * @param payType
     * @return
     */
    public static Pay createPay(String payType) {
        if (payType == null) {
            return null;
        } else if ("ALI_PAY".equals(payType)) {
            return new AliPay();
        } else if ("WEICHAT_PAY".equals(payType)) {
            return new WeichatPay();
        }
        return null;

    }
}

2. 工厂方法模式

工厂方法模式又称工厂模式,是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。通过工厂父类定义负责创建产品的公共接口,通过子类来确定所需要创建的类型。
相比简单工厂而言,此种方法具有更多的可扩展性和复用性,同时也增强了代码的可读性。
将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类类决定应该实例化哪一个类。

  • 核心组成
    • IProduct : 抽象产品类,描述所有实例所共有的公共接口
    • Product : 具体产品类, 实现抽象产品类的接口,工厂类创建对象,如果有多个需要定义多个
    • IFactory : 抽象工厂类,描述具体工厂的公共接口
    • Factory : 具体工厂类,实现创建产品类对象,实现抽象工厂类的接口,如果有多个需要定义多个

在这里插入图片描述

  • 优点

    • 符合开闭原则,增加一个产品类,只需要实现其他具体的产品类和具体的工厂类;
    • 符合单一职责原则,每个工厂只负责生产对应得产品
    • 使用者只需要知道产品的抽象类,无需关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则
  • 备注

    • 迪米特法则 : 最少知道原则,实体应当尽量少地与其他实体之间相互发生作用
    • 依赖倒置原则 : 针对接口编程,依赖于抽象而不依赖于具体
    • 里氏替换原则 : 俗称LSP,任何基类可以出现的地方,子类一定可以出现,对实现抽象化的的具体步骤的规范
  • 缺点

    • 增加一个产品类,需要实现对应得具体工厂类和具体产品类
    • 每个产品需要有对应的具体工厂和具体产品类
/**
 * 抽象产品
 */
public interface Pay {

    // 统一下单抽象方法
    void unifiedorder();
}
/**
 * 具体产品1
 */
public class AliPay implements Pay {
    @Override
    public void unifiedorder() {
        System.out.println("支付宝支付---统一下单逻辑");
    }
}
/**
 * 具体产品2
 */
public class WeichatPay implements Pay {
    @Override
    public void unifiedorder() {
        System.out.println("微信支付---统一下单逻辑");
    }
}
/**
 * 抽象工厂方法
 */
public interface PayFactory {

    public Pay getPay();
}
/**
 * 具体产品工厂
 */
public class AliPayFactory implements PayFactory{
    @Override
    public Pay getPay() {
        return new AliPay();
    }
}
/**
 * 具体产品工厂
 */
public class WechatPayFactory implements PayFactory {
    @Override
    public Pay getPay() {
        return new WeichatPay();
    }
}
/**
 * 具体实现
 */
public static void main(String[] args) {
	PayFactory aliPayFactory = new AliPayFactory();
	Pay aliPay = aliPayFactory.getPay();
	aliPay.unifiedorder();

	PayFactory wechatPayFactory = new WechatPayFactory();
	Pay wechatPay = wechatPayFactory.getPay();
	wechatPay.unifiedorder();
}

3. 抽象工厂模式

工厂模式有3种不同的实现方式。
简单工厂模式:通过传入的相关的类型来返回相应的类,这种方式比较单一,可扩展性相对较差
工厂方法模式:通过实现类实现相应的方法来决定相应的返回结果,这种方式的可扩展性比较强
抽象工厂模式:基于上述两种模式的拓展,是工厂方法模式的升级版,当需要创建的产品有多个产品线时使用抽象工厂模式是比较好的选择
抽象工厂模式在Spring中应用得最为广泛的一种设计模式

工厂方法模式引入工厂等级结构问题,解决了简单工厂模式中工厂类职责过重的问题。但工厂方法模式中每个工厂只创建一类具体类的对象,后续发展可能会导致工厂类过多,因此将一些相关的具体类组成一个"具体类族",由同一个工厂来统一生产,强调的是一系列相关的产品对象!!!

在这里插入图片描述
如上图所示,将A,B,C,D表示为车的品牌,方形、棱形、椭圆形表示为轿车,跑车,SUV。那么产品族可以对应成A,B,C,D对应得品牌族,产品等级结构对应为车的类型。由一个超级工厂来创建这些各个品牌的轿车,跑车,SUV。

如何实现使用一个超级工厂实现上述过程:

  1. 定义三个接口SUV,轿车,跑车的接口
  2. 创建具体的SUV,轿车,跑车产品
  3. 创建抽象工厂CarFactory接口,里面有三个方法createSUV,create轿车,create跑车
  4. 创建宝马产品族 BMWFactory,实现CarFactory抽象工厂
  5. 创建奥迪产品族 AudiFactory,实现CarFactory抽象工厂
  6. 定义一个超级工厂创造器,通过传递参数获取对应的工厂

对应UML类图如下
在这里插入图片描述

由于演示DEMO,下边代码只演示SUV和跑车的产品组

public interface PCFactory {
    // 创建跑车
    public void createPaoche();
}
public interface SUVFactory {
    // 创建SUV
    public void createSUVCar();
}
public class AudiPCCar implements PCFactory {
    @Override
    public void createPaoche() {
        System.out.println("建造奥迪跑车");
    }
}
public class AudiSUVCar implements SUVFactory {
    @Override
    public void createSUVCar() {
        System.out.println("建造奥迪SUV");
    }
}
public class BMWPCCar implements PCFactory {
    @Override
    public void createPaoche() {
        System.out.println("建造宝马跑车");
    }
}
public class BMWSUVCar implements SUVFactory {
    @Override
    public void createSUVCar() {
        System.out.println("建造宝马SUV");
    }
}
// 超级工厂
public interface CarFactory {

    PCFactory createPC();

    SUVFactory createSUV();
}
public class AudiCarFactory implements CarFactory {
    @Override
    public PCFactory createPC() {
        return new AudiPCCar();
    }

    @Override
    public SUVFactory createSUV() {
        return new AudiSUVCar();
    }
}
public class BMWCarFactory implements CarFactory {
    @Override
    public PCFactory createPC() {
        return new BMWPCCar();
    }

    @Override
    public SUVFactory createSUV() {
        return new BMWSUVCar();
    }
}
/**
 * 超级工厂
 */
public class CarProducer {

    public static CarFactory getCar(String type) {
        if (type.equals("BMW")){
            return new BMWCarFactory();
        } else if (type.equals("AUDI")) {
            return new AudiCarFactory();
        }
        return null;
    }
}

// Main函数调用
CarFactory carfactory = CarProducer.getCar("AUDI");
carfactory.createSUV().createSUVCar();
carfactory.createPC().createPaoche();

工厂方法模式和抽象工厂方法模式选择:
当抽象工厂方法模式中每一个具体工厂类只创建一个产品对象时,抽象工厂模式可退化成工厂方法模式

优点
  • 当一个产品族中的多个对象被设计成一起工作时,它能保证使用方始终只使用同一个产品族中的对象
  • 产品等级结构扩展容易,如果需要增加多一个产品等级,只需要增加新的工厂类和产品类即可,比如增加建造奔驰SUV和奔驰跑车
缺点
  • 产品族扩展困难,要增加一个系列的某一产品,既要在抽象的工厂和抽象产品里修改代码,不是很符合开闭原则
  • 增加了系统的抽象性和理解难度
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值