为了账号安全,请及时绑定邮箱和手机立即绑定

工厂模式

标签:
JavaScript

首先,简单工厂模式不属于23中涉及模式,简单工厂一般分为:普通简单工厂、多方法简单工厂、静态方法简单工厂。

A、简单工厂模式

简单工厂模式模式分为三种:

A1、普通

就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图:
[图片上传失败...(image-13f411-1537173544176)]

举例如下:(我们举一个发送邮件和短信的例子)

首先,创建二者的共同接口:

public interface Sender {    public void Send();
}

其次,创建实现类:

public class MailSender implements Sender {    @Override
    public void Send() {
        System.out.println("this is mailsender!");
    }
}
public class SmsSender implements Sender {    @Override
    public void Send() {
        System.out.println("this is sms sender!");
    }
}

最后,建工厂类:

public class SendFactory {    public Sender produce(String type) {        if ("mail".equals(type)) {            return new MailSender();
        } else if ("sms".equals(type)) {            return new SmsSender();
        } else {
            System.out.println("请输入正确的类型!");            return null;
        }
    }
}

我们来测试下:

public class FactoryTest {

    public static void main(String[] args) {
        SendFactory factory = new SendFactory();
        Sender sender = factory.produce("sms");
        sender.Send();
    }
}

输出:this is sms sender!

A2、多个方法

是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。关系图:

[图片上传失败...(image-d4ea0d-1537173544176)]

将上面的代码做下修改,改动下SendFactory类就行,如下:

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

测试类如下:

public class FactoryTest {
    public static void main(String[] args) {
        SendFactory factory = new SendFactory();
        Sender sender = factory.produceMail();
        sender.Send();
    }
}

输出:this is mailsender!

A3、多个静态方法

将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

public class SendFactory {

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

    public static void main(String[] args) {
        Sender sender = SendFactory.produceMail();
        sender.Send();
    }
}

输出:this is mailsender!

总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

B、工厂方法模式(Factory Method)

简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

[图片上传失败...(image-8c8dfb-1537173544176)]

public interface Sender {    public void Send();
}

两个实现类:

public class MailSender implements Sender {    @Override
    public void Send() {
        System.out.println("this is mailsender!");
    }
}
public class SmsSender implements Sender {    @Override
    public void Send() {
        System.out.println("this is sms sender!");
    }
}

在提供一个接口:

public interface Provider {    public Sender produce();
}

两个工厂类:

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

测试类:

public class Test {

    public static void main(String[] args) {
        Provider provider = new SendMailFactory();
        Sender sender = provider.produce();
        sender.Send();
    }
}

其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!

C、抽象工厂模式

假设,时代进步了,通过邮件发送语音了,通过短信也可发送语音了
定义一个接口:

public interface Caller {    public void call();
}

两个实现类:

public class EmailCaller implements Caller {    @Override
    public void call() {
        System.out.println("this is mailcaller!");
    }
}
public class SmsCaller implements Caller{    @Override
    public void call() {
        System.out.println("this is smscaller!");
    }
}

在提供一个接口:

public interface Provider {    Sender produceSender();    Caller produceCaller();
}

两个工厂类:

public class EmailFactory implements Provider{    @Override
    public Sender produceSender() {        return new MailSender();
    }    @Override
    public Caller produceCaller() {        return new EmailCaller();
    }
}
public class SmsFactory implements Provider {    @Override
    public Sender produceSender() {        return new SmsSender();
    }    @Override
    public Caller produceCaller() {        return new SmsCaller();
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        Provider provider = new SmsFactory();
        Sender sender = provider.produceSender();
        Caller caller = provider.produceCaller();
        sender.Send();
        caller.call();
    }
}

只有一个Send的封装类和Send操作类时,我们只用到了工厂方法模式,而且也只需要使用到工厂方法模式。但是显然现在我们的功能已经不止一个Send了,而 Send 和 call 又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,就需要使用到专门解决这种问题的模式:抽象工厂模式。这时候再回过头去看DP对抽象工厂模式的定义就不难理解了。

所以抽象工厂与工厂方法模式的区别在于:抽象工厂是可以生产多个产品的,例如 SmsFactory 里可以生产 produceSender 以及 produceCaller 两个产品,而这两个产品又是属于一个系列的,因为它们都是属于Sms的功能。而工厂方法模式则只能生产一个产品,例如之前的 SendSmsFactory 里就只可以生产一个 Sender 产品。

示意图:


webp

image

总结:

工厂方法模式和抽象工厂模式不好分清楚,他们的区别如下:

工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品。

区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。

抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承。

对于java来说,你能见到的大部分抽象工厂模式都是这样的:
---它的里面是一堆工厂方法,每个工厂方法返回某种类型的对象。

比如说工厂可以生产鼠标和键盘。那么抽象工厂的实现类(它的某个具体子类)的对象都可以生产鼠标和键盘,但可能工厂A生产的是罗技的键盘和鼠标,工厂B是微软的。

这样A和B就是工厂,对应于抽象工厂;
每个工厂生产的鼠标和键盘就是产品,对应于工厂方法;

用了工厂方法模式,你替换生成键盘的工厂方法,就可以把键盘从罗技换到微软。但是用了抽象工厂模式,你只要换家工厂,就可以同时替换鼠标和键盘一套。如果你要的产品有几十个,当然用抽象工厂模式一次替换全部最方便(这个工厂会替你用相应的工厂方法)

所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线



作者:伯羽君
链接:https://www.jianshu.com/p/17f08c81b349


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消