普通工厂模式:传入参数根据参数调用调用不同接口。
优点:只需要写一个工厂方法,根据参数不同调用构建不同对象,
缺点:如果该参数在工厂内不存在会报错,
使用场景如:消息(短信和邮件)发送接口,调用接口中一个方法—根据参数构建对象;
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:30:55
* 类说明:抽象接口
*/
public interface SenderService {
public void Send();
}
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:31:55
* 类说明
*/
public class MailSender implements SenderService{
public void Send() {
System.out.println("this is mailSend");
}
}
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:33:21
* 类说明
*/
public class SmsSender implements SenderService{
public void Send() {
System.out.println("this is smsSend");
}
}
以上两个实现类都实现了SenderService调用的是send方法;但是在实际使用中不知道具体返回的是那个实现对象,所以通过工厂模式中的普通工厂方式模式来区分返回对象,实现调用,下面是工厂方法模式构建对象
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:36:03
* 类说明
*/
public class SendFactory {
//普通工厂通过参数来确实是构建那个对象
public SenderService produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
} else {
System.out.println("请输入正确的类型!");
return null;
}
}
返回的两个对象分别是MailSender和SmsSender,所以可以通过这个对象可以获得具体实现方法;
测试类:
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:35:19
* 类说明
*/
public class TestFM {
@Test
public void test() {
SendFactory sFactory = new SendFactory();//1,初始化工厂
SenderService sender =sFactory.produce("mail");//2,根据参数构建对象(这里返回的sender实际上是MailSender),所以下面sender.send()调用的是MailSender实现方法
sender.Send();//
}
}
同样的列子–根据工厂方法名字构建对象
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:36:03
* 类说明
*/
public class SendFactory {
public SenderService produceSms(){
return new SmsSender();
}
public SenderService produceEmail(){
return new MailSender();
}
测试:
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:35:19
* 类说明
*/
public class TestFM {
@Test
public void test() {
SendFactory sFactory = new SendFactory();
SenderService sender =sFactory.produceEmail();//多工厂方法模式:分别创件工厂,调用时直接对当前调用进行构建,
sender.Send();
}
}
访问直接调用的是对应的工厂方法,返回是对应的对象
静态工厂方法模式:多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可,
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:36:03
* 类说明
*/
public class SendFactory {
//静态工厂方法模式:多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可
public static SenderService staticProduceMail(){
return new MailSender();
}
public static SenderService staticProduceSms(){
return new SmsSender();
}
}
调用方式比较简单。工厂不需要实例化;
测试:
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:35:19
* 类说明
*/
public class TestFM {
@Test
public void test() {
SenderService sender =SendFactory.staticProduceMail();//静态工厂方法模式:多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可,
sender.Send();
}
}
工厂模式实际应用:目前我在一个互金项目中的支付环节用到了,把第三方支付接口调用部分的参数全部封装在了一个工厂中,每个支付业务只需要调用对应的接口,或者传入接口对应的接口参数;三种方式都有用到,具体看业务需要。使用的目的主要是在一个项目中不同的业务可以使用同一个支付实现类(工厂),免得每个业务都写一遍支付接口参数组装。
抽象工厂模式:为了避免工厂随着义务的变化一直被改,出现了抽象工厂,抽象工厂的出现符合程序设计中的开闭原则,实际上是把工厂类抽象后,提供给外部接口,同时把不同的业务分开在不同的工厂中,实现抽象出来的接口,外部直接调用接口就可以,
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:30:55
* 类说明:工厂抽象接口
*/
public interface Provider {
public SenderService produce();
}
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:36:03
* 类说明:工厂实现类
*/
public class SendEmailFactory implements Provider{
public SenderService produce() {
return new SmsSender();
}
}
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月6日 上午11:36:03
* 类说明
*/
public class SendSmsFactory implements Provider{
public SenderService produce() {
return new MailSender();
}
}
测试
Provider provider = new SendEmailFactory(); //实例化的直接是业务对应的工厂类
SenderService sender = provider.produce();//所以返回的工厂对象一定是email对象
sender.Send();//调用的一定是email发送方法
抽象工厂的好处,如果需要扩展别的业务只需要创建对应的工厂(编写构建对象),让工厂实现工厂接口(Provider接口),把接口对外开发就可以,如code验证:
public classCodeFactory implements Provider{
public SenderService produce() {
return new MailSender();
}
}
添加code对象(其实就是需要构建的对象)
测试
Provider provider = new classCodeFactory (); //实例化的直接是业务对应的工厂类
SenderService sender = provider.produce();//所以返回的工厂对象一定是code对象
sender.Send();//调用的一定是code发送方法
就完成了扩展。