Java-工厂设计模式
- 2019 年 10 月 14 日
- 筆記
一、关于工厂设计模式
介绍:设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,
并且是通过使用一个共同的接口来指向新创建的对象。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
分类:普通简单工厂、多个方法的简单工厂、多个静态方法的简单工厂、工厂设计模式。
二、代码实现
简单工厂:就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图
举例如下:(我们举一个发送邮件和短信的例子)
首先,创建二者的共同接口:
Sender
package pers.hupo.hupow.factory; /** * @author hupo * 创建一个接口 * */ public interface Sender { void Send(); }
其次,创建实现类:
MailSender
package pers.hupo.hupow.factory; /** * @author hupo * Sender实现类 * */ public class MailSender implements Sender { @Override public void Send() { System.out.println("this mail message"); } }
SmsSender
package pers.hupo.hupow.factory; /** * @author hupo * Sender实现类 * */ public class SmsSender implements Sender { @Override public void Send() { System.out.println("this sms message"); } }
最后,建工厂类
package pers.hupo.hupow.factory; /** * @author hupo * 工厂类 * */ public class SendFactory { public Sender produce(String type) { if ("mail".equals(type)) { return new MailSender(); } if ("sms".equals(type)) { return new SmsSender(); } return null; } }
测试方法
package pers.hupo.hupow.factory; public class FactoryTest { public static void main(String[] args) {
SendFactory sendFactory = new SendFactory(); Sender sender = sendFactory.produce("sms"); sender.Send(); } }
输出结果:
this sms message
多个方法的简单工厂:是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,
而多个工厂方法模式是提供多个工厂方法,分别创建对象。关系图如下
将工厂类改动一些 如下:
package pers.hupo.hupow.factory; /** * @author hupo * 工厂类 * */ public class SendFactory { /* * 多方法的简单工厂 */ public Sender produceMail() { return new MailSender(); } public Sender produceSms() { return new SmsSender(); } }
修改一下测试类
SendFactory sendFactory = new SendFactory(); Sender sender = sendFactory.produceMail(); sender.Send();
输出结果:
this mail message
多个静态方法简单工厂:将上面的多个工厂类里的方法置为静态的,不需要创建实例,直接调用即可。如下
package pers.hupo.hupow.factory; /** * @author hupo * 工厂类 * */ public class SendFactory { /* * 静态多方法工厂 * */ public static Sender produceMail() { return new MailSender(); } public static Sender produceSms() { return new SmsSender(); } }
测试
/*静态多方法*/ Sender sender = SendFactory.produceMail(); sender.Send();
输出:
this mail messageb
总体来说,简单工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,
第一种如果传入的字符串有误,不能正确创建对象(当然你可以做一个返回报错信息的类),第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。
三、工厂方法模式(Factory Method)
简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则。
所以,从设计角度考虑,有一定的问题,如何解决?就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
首先还是创建发送信息端的接口
Sender
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工厂方法设计模式-信息接口 */ public interface Sender { void Send(); }
两个实现类
MailSender
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工厂方法设计模式-实现类 * */ public class MailSender implements Sender { @Override public void Send() { System.out.println("this is mailSender"); } }
SmsSender
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工厂方法设计模式-实现类 * */ public class SmsSender implements Sender { @Override public void Send() { System.out.println("this is smsSender"); } }
然后再来创造工厂类接口(大内统管( ̄▽ ̄)”)
Provider
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工厂方法设计模式-工厂类接口 * */ public interface Provider { Sender produce(); }
实现类工厂
SendMailFactory
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工厂类设计方法-实现方法 * */ public class SendMailFactory implements Provider { @Override public Sender produce() { return new MailSender(); } }
SendSmsFactory
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 接口实现方法 * */ public class SendSmsFactory implements Provider { @Override public Sender produce() { return new SmsSender(); } }
完成之后写个测试类来试试
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 测试类 * */ public class FactoryMethodTest { public static void main(String[] args) { Provider provider = new SendMailFactory(); Sender sender = provider.produce(); sender.Send(); } }
输出结果
this is mailSender
加个工厂类扩展试试
添加哲学家van 和Billy 继承sender
van
package pers.hupo.hupow.FactoryMethod; public class VanSender implements Sender { @Override public void Send() { System.out.println("f♂ck y♂u"); } }
View Code
Billy
package pers.hupo.hupow.FactoryMethod; public class BillySender implements Sender { @Override public void Send() { System.out.println("帕秋莉♂GO"); } }
View Code
然后使用SendBillyFactory 继承Provider
package pers.hupo.hupow.FactoryMethod; public class SendBillyFactory implements Provider { @Override public Sender produce() { return new BillySender(); } }
View Code
测试类
/*哲学家测试*/ Provider provider = new SendBillyFactory(); Sender sender = provider.produce(); sender.Send();
View Code
输出:
帕秋莉♂GO
其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!