设计模式学习---Java工厂模式(Factory)

普通工厂模式

概念

普通工厂方法模式就是建立一个工厂类,对实现了同一接口的不同实现类进行实例的创建。实际上就是new对象

类图
类图-工厂模式 来自拉勾教育
右侧一个接口(Sender)两个实现类(MailSender、SmsSender),左侧工厂类(SendFactory)produce方法有一个String类型的参数type,返回值为Sender(构成多态)。代码如下:
Sender

public interface Sender {
    // 自定义抽象方法
    void send();
}

MailSender

public class MailSender implements Sender {
    @Override
    public void send() {
        System.out.println("正在发送邮件!!");
    }
}

SmsSender

public class SmsSender implements Sender {
    @Override
    public void send() {
        System.out.println("正在发送短信!!");
    }
}

SendFactory

public class SendFactory {
    // 自定义成员方法实现对象的创建
    public Sender produce(String type){
        if("mail".equals(type)){
            return new MailSender();
        }
        if("sms".equals(type)){
            return new SmsSender();
        }
        return null;
    }
}

测试类SendFactoryTest 及优缺点说明

public class SendFactoryTest {
    public static void main(String[] args) {
        // 优点:扩展性和可维护性更强! 尤其是在创建大量对象的前提下
        // 缺点:代码略复杂,可读性略差
        // 最主要的缺点在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,并且可能出现空指针异常。
        
        // 1.声明工厂类类型的引用指工厂类类型的对象
        SendFactory sf = new SendFactory();
        // 2.调用生产方法来实现对象的创建
        Sender sender = sf.produce("mail");
        // 3.使用对调用方法模拟发生的行为
        sender.send();

        System.out.println("-----------------------------------------");
        /*
        // 优点:代码简单,可读性强   在创建单个对象时有优势
        // 缺点:扩展性和可维护性略差
        Sender sender1 = new MailSender();
        sender1.send();
        */
    }
}

运行结果:
在这里插入图片描述
对普通工厂类可能出现空指针异常的缺点,我们做出了一个改进:多个工厂方法模式

多个工厂方法模式

类图-多个工厂方法模式 来自拉勾教育

多个工厂模式与普通工厂模式在类图上可以看出,主要的不同就是普通工厂模式是一个方法创建多个对象,多个工厂模式变成了 两个方法各自创建自己的对象。

public class SendFactory {
    // 缺点:在多个工厂方法模式中,为了能够正确创建对象,先需要创建工厂类的对象才能调用工厂类中的生产方法。
    // 就是说需要在main()方法里面创建SendFactory这个类型的对象,才可以调用
    public Sender produceSms(){
        return new SmsSender();
    }
    public Sender produceMail(){
        return new MailSender();
    }
}

这样,就可以解决因为传字符串参数出错导致的空指针问题了。但是还是有一些问题,我们继续优化。
在代码块中我们已经提到了该方法的缺点,就是在调用方法的时候我们还需要先new()一个工厂类的对象才可以调用它的方法,解决办法当然有,而且还很简单。我们只需要把方法提升到类层级,使方法可以通过 类名. 的方式调用就可以了,也就是说,给每一个方法加上static关键字修饰,变成:静态工厂方法模式

静态工厂方法模式

类图-静态工厂方法模式  来自拉勾教育
SendFactory

public class SendFactory {
    public static Sender produceSms(){
        return new SmsSender();
    }
    public static Sender produceMail(){
        return new MailSender();
    }
}

SendFactoryTest

public class SendFactoryTest {
    public static void main(String[] args) {
        SendFactory.produceMail();
        SendFactory.produceSms();
 	}
}

至此,我们已经得到了很优秀的工厂方法模式的代码。
工厂方法模式的实际意义
工厂方法模式适合:凡是出现了大量的产品(对象)需要创建,且拥有共同的接口的时候,可以通过工厂方法模式进行创建。
工厂方法模式的主要缺点
类的创建依赖于工厂类,也就是说,如果需要拓展新的业务,生产新的产品,就必须去修改工厂的类代码。我们学习设计模式的时候讲到过,要遵循的开闭原则,在这里并没有实现。所以还存在一定的问题,并没有做到对修改关闭。这里我们提出了另一个模式。。。

抽象工厂模式

类图-抽象工厂模式 来自拉勾教育
从类图中不难看出抽象工厂模式与之前的工厂模式的区别,我们直接来看代码:
Provider

public interface Provider {
    // 自定义抽象方法描述产品的生产
    Sender produce();
}

MailSendFactory

public class MailSendFactory implements Provider {
    @Override
    public Sender produce() {
        return new MailSender();
    }
}

SmsSendFactory

public class SmsSendFactory implements Provider {
    @Override
    public Sender produce() {
        return new SmsSender();
    }
}

SendFactoryTest

public class SendFactoryTest {
    public static void main(String[] args) {
        Provider provider = new MailSendFactory();
        Sender sender1 = provider.produce();
        sender1.send();
        provider = new SmsSendFactory();
        Sender sender2 = provider.produce();
        sender2.send();
    }
}

结果:
在这里插入图片描述
优点说明:
我们说抽象工厂模式解决了上面几个工厂模式没有实现的开闭原则,如果需要拓展新的业务,生产新的产品,使用抽象工厂模式就只需要增加一个类并且让这个类实现Provider这个接口就可以了,又得到了扩展,有没有修改原有的代码,对工厂模式来说简直完美!

到此,工厂模式学习完毕。

本文章只是个人学习,内容不多,也都很基础,如果内容上有什么问题,还请大家多多指教!!

一定会有那么一天,我也能用上这句话:“本性闲散,最终却也跟上了前辈的步伐”

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值