设计模式之工厂模式

顾名思义,由工厂创建对象,返回对象给你,而你不需要关心对象的创建,你只需要获取到对象,执行与对象相关逻辑即可。

假设,需要发送邮件和发送短信,你不需要关心邮箱对象是怎么创建的,内部有什么初始化,只需要获取到邮箱对象,然后sendMail即可。

普通工厂模式

如上图的模式,CommonFactory使用produce负责生产出对应的发送设备,根据传入的参数决定是邮件发送,还是短信发送。

不需要关心MailSender和SmsSender发送需要什么初始化条件,完全由工厂去初始化。

用户只需要拿到Sender,然后调用send()方法发送对应数据即可。

在这里插入图片描述

发送者

/**
 * @author lw
 * @date 2022/3/28 0028
 * @description  发送者
 */
public interface Sender {

    void send(String content);
}

/**
 * @author lw
 * @date 2022/3/28 0028
 * @description  短信发送
 */
public class SmsSender implements Sender {

    //移动发送短信需要的入网条件
    private String smsKey;
    private String smsAccess;

    public SmsSender(String smsKey,String smsAccess){
        this.smsAccess = smsAccess;
        this.smsKey = smsKey;
    }

    @Override
    public void send(String content) {
        System.out.println("短信发送:"+content);
    }
}

/**
 * @author lw
 * @date 2022/3/28 0028
 * @description  邮件发送
 */
public class MailSender implements Sender {

    //网易发送邮件需要的条件
    private String accessKey;

    public MailSender(String accessKey){
        this.accessKey = accessKey;
    }

    @Override
    public void send(String content) {
        System.out.println("邮件发送:"+content);
    }
}

可以看出邮件发送需要发送条件短信发送也需要发送条件

这里把发送条件简化了,如果需要一大堆判断发送条件呢,选择运营商等等呢?难道每次创建SmsSender对象都要一大堆判断条件来初始化这个?

工厂

/**
 * @author lw
 * @date 2022/3/28 0028
 * @description  普通工厂
 */
public class CommonFactory {

    //移动发送短信需要的入网条件
    private String smsKey;
    private String smsAccess;

    //网易发送邮件需要的条件
    private String accessKey;

    /**
     * 生产线
     * @param sendType
     * @return
     */
    public Sender produce(String sendType){
        if("sms".equals(sendType)){
            return new SmsSender(smsKey,smsAccess);
        }else if("mail".equals(sendType)){
            return new MailSender(accessKey);
        }
        return null;
    }
}

使用工厂产出SmsSender和MailSender对象,不需要用户在调用时还关心这些入网条件,也不需要获取这些key什么的。完全由工厂去做。

调用

CommonFactory factory = new CommonFactory();
Sender sender = factory.produce("sms");
sender.send("hello world");

此处是直接传入字符串,当然也可以用枚举类来规范代码,防止出错。

多工厂方法模式

顾名思义,就是多个工厂方法,也就是多个方法。

为了防止传参出错,返回一个Null给调用者,那就分成多个方法来生产不同的对象。

将sms和mail的生产线拆开,分成两条生产线,一条生产SmsSender对象,一条生产MailSender对象。
在这里插入图片描述

/**
     * 短信生产线
     * @return
     */
    public Sender produceSms(){
        return new SmsSender(smsKey,smsAccess);
    }

    /**
     * 邮件生产线
     * @return
     */
    public Sender produceMail(){
        return new MailSender(accessKey);
    }

调用者

MoreMethodFactory factory = new MoreMethodFactory();
Sender sender = factory.produceSms();
sender.send("hello world");

这样调用者就不需要关心传什么参数,只需要调用不同方法即可。

静态工厂模式

即将方法使用static静态化,主要是为了不需要初始化工厂对象。

不需要初始化工厂后,需要关心生产线,而不需要关心工厂初始化信息。
在这里插入图片描述

/**
     * 生产线
     * @param sendType
     * @return
     */
    public static Sender produce(String sendType){
        if("sms".equals(sendType)){
            return new SmsSender(smsKey,smsAccess);
        }else if("mail".equals(sendType)){
            return new MailSender(accessKey);
        }
        return null;
    }

调用者

Sender sender = StaticFactory.produce("sms");
sender.send("hello world");

抽象工厂模式

上述工厂模式中,每加入一种发送模式都需要修改工厂信息,这里不提什么不符合开闭原则。

就说一个场景,A和B的SmsSender的初始化key不一样呢?难道说new一个Factory,然后传入初始化key?

后续又要加入produceWeixin()发送方法呢…

这样就可以产生一个如上图所示的抽象工厂Factory,这个抽象工厂就只有一个produce()方法,后续无论是SmsFactory还是MailFactory都可以实现这个抽象工厂。

/**
 * @author lw
 * @date 2022/3/28 0028
 * @description 抽象工厂
 */
public interface Factory {

    Sender produce();
}


/**
 * @author lw
 * @date 2022/3/28 0028
 * @description 邮件工厂
 */
public class MailFactory implements Factory {

    //网易发送邮件需要的条件
    private String accessKey;

    @Override
    public Sender produce() {
        return new MailSender(accessKey);
    }
}


/**
 * @author lw
 * @date 2022/3/28 0028
 * @description  短信工厂
 */
public class SmsFactory implements Factory {

    //移动发送短信需要的入网条件
    private String smsKey;
    private String smsAccess;

    @Override
    public Sender produce() {
        return new SmsSender(smsKey,smsAccess);
    }
}

抽象工厂模式,易于后期拓展,但是每加入一种模式都需要创建一种工厂。

想象一下有30种消息发送模式,难道你需要创建30个类?

总结

以下几种场景可以考虑工厂模式:

  1. 需要繁杂的对象初始化;
  2. 多个对象有共同的功能,同时还可以抽象出一个共同的抽象对象;

至于说是用普通工厂模式,多工厂方法模式还是抽象工厂模式,这就看业务复杂度以及后续是否需要扩展等要素。

下面这种一般项目中用的多,也易于扩展,很多方法都是写在MoreMethodFactory中,等这个类复杂了就可以抽离出一些代码。
在这里插入图片描述

从来没有一步到位的设计,都是不断优化,不断重构。

就如同工厂一样,一开始是一个小工厂CommonFactory,生产各种东西,接到什么订单就生产什么。

等规模大了,就考虑扩展多条生产线,变成MoreMethodFactory,各个生产线负责生产不同东西。

等规模继续扩展,就变成AbstractFactory,就可以开设多个工厂,有SmsFactory和MailFactory等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值