设计模式之工厂模式(一)
在正式开始之前,我们要先明白为什么用它,毕竟实现功能的途径有很多,为什么要用个固定的模式,反而感觉开发变得困难了,其实并非如此,开发也意味着需要维护,用这些设计模式一能提高你的代码质量,同时也能使你程序的可维护性升高,与此同时,各位猿友,既然在这条路上想要走得远,那么必经之路就是剖析大师们的源码,大师们代码中将这些设计模式已经用的出神入化了,假若你想走得远,想对源码理解深入,设计模式也是一条必经之路,之后我也会陆续的开始写源码解析的记录博客,希望能与猿友们一起探讨。
下面我们正式开始:
工厂模式其实有三种分类:简单工厂模式,工厂方法模式,抽象工厂模式,在这里要提一下的是简单工厂模式,它并不是23中设计模式中的,但在这里提及也是为了能够一步步深入了解工厂模式,按照这个先后顺序我们来一遍撸理论,一遍撸代码。
我们先想一个应用场景,现在需要做一个短信发送和一个邮件发送类,我不想分开写这两个类,因为如果那样的话我调用任何一个方法时都需要new,可能还需要初始化一些参数,我希望将这一系列的动作都封装起来,我要短信发送,你就直接给我发送短信的方法就行,照着这个思路我们来实现下:
简单工厂模式
1.首先创建一个接口Send
public interface Send {
public void send();//无论短信还是邮件都是发送的动作,只不过具体实现不同
}
2.创建发送短信以及发送邮件的类并实现Send接口
public class SendMsg implements Send {
@Override
public void send() {
System.out.println("Message Sending.........");
}
}
3.创建工厂类(根据用户的输入发送短信或者邮件)
public class SimpleFactory {
public void sendSmt(String type){
Send send = null;
if("email".equals(type)){
send = new SendEmail();
send.send();
}else if("msg".equals(type)){
send = new SendMsg();
send.send();
}
.........
}
}
4.测试结果
public class FactoryTest {
@Test
public void testFactory(){
SimpleFactory factory = new SimpleFactory();
factory.sendSmt("email");//发送邮件
factory.sendSmt("msg");//发送短信
}
}
Email Sending........
Message Sending.........
这就是简单工厂模式,发现其实不难,自己想想是能写出来的,不过就是用factory去统一创建发送短信和发送邮件的实例,如果想统一创建,那么让你要创建的实例统一去实现一个接口,通过输入的type(自己定的)来判断向上造型哪一个实例就可以实现了。
这样有什么好处相信看了代码已经很清晰了。
工厂模式
而工厂模式则是对简单工厂模式的改进,接下来我们来看下工厂模式的具体实现
说下具体步骤:和简单工厂基本一致,不同点在于工厂的改动和测试方法的改动,其余和简单工厂是一样的。
1.工厂模式的工厂类
public class Factory {
public Send produceMsg(){
return new SendMsg();
}
public Send produceEmail(){
return new SendEmail();
}
}
2.测试代码
public class FactoryTest {
@Test
public void testFactory(){
Factory factory = new Factory();
Send email = factory.produceEmail();
email.send();
Send msg = factory.produceMsg();
msg.send();
}
}
结果我就不在这里赘述了,从代码上很容易看出工厂模式是对简单工厂的工厂类再次进行简化,使msg和email都有了属于自己的工厂方法。但是这时候就有个疑问了,假如我现在除了发送短信和发送邮件外,我可能还需要添加发送分享文章之类其他的需求,从以上的代码来看也不难,我只要在Factory类中再加一个不就好了,但是我们在开发的过程中不难发现,源码是尽量不要动的,你需要什么功能最好是在不影响源码的基础上进行添加,那么问题来了,如何做到不改动现有factory的前提下加入新的功能?这就是我们接下来要说的抽象工程方法。
抽象工厂方法
我们先不撸代码,思考下这个方法,我们都知道java命名是见名知意,这些工厂的名称也是如此,抽象工厂方法,重点在于抽象,之前我们在写工厂方法的时候利用造型创建对应的实例,那么在这里也是一个道理。抽象工厂方法是工厂方法中最不容易理解的部分,但是也是实际开发过程中比较常用的方法,所以这个方法我会从头撸一遍代码,虽然部分代码和之前工厂方法相同,但还是给个比较全的这样猿友们如果有兴趣自己敲一个也方便。
1.创建send接口
public interface Send {
void send();
}
2.创建工厂接口
public interface Provider {
public Send produce();
}
3.创建短信和邮件类并实现send接口
public class SendEmail implements Send {
@Override
public void send() {
System.out.println("Email Sending........");
}
}
public class SendMsg implements Send {
@Override
public void send() {
System.out.println("Message Sending.......");
}
}
4.创建发送短信和发送邮件工厂类并继承Provider
public class SendEmailFactory implements Provider{
@Override
public Send produce() {
return new SendEmail();
}
}
5.测试类
public class TestFactory {
@Test
public void testFactory(){
Provider msg = new SendMsgFactory();
msg.produce().send();
Provider email = new SendEmailFactory();
email.produce().send();
}
}
Message Sending.......
Email Sending........
这就是抽象工厂了,我在刚开始撸抽象工厂代码的时候有提到一个问题,如何在不动源码的基础上添加新的功能对吧,在开始添加新功能之前我们捋一下思路,具体的发送方法我们是通过实现send接口进行造型得到我们对应的实例,而我们现在的程序,工厂类也实现了Provider接口,我们也是通过造型得到对应的实例,假如我们现在需要添加实施发送状态的功能,只需要在工厂类中实现Provider接口,在发送方法中实现send接口就能在不改动任何源码的情况下添加新的功能,有了思路我们来撸代码。
1.创建SendCurrent类并实现Send接口
public class SendCurrent implements Send{
@Override
public void send() {
System.out.println("CurrentMessage Sending.........");
}
}
2.创建SendCurrentFactory并实现Provider接口
public class SendCurrentFactory implements Provider{
@Override
public Send produce() {
return new SendCurrent();
}
}
功能添加完毕,是不是没有改动之前的任何代码?我们来测试下结果如何
public class TestFactory {
@Test
public void testFactory(){
Provider msg = new SendMsgFactory();
msg.produce().send();
Provider current = new SendCurrentFactory();
current.produce().send();
Provider email = new SendEmailFactory();
email.produce().send();
}
}
Message Sending.......
CurrentMessage Sending.........
Email Sending........
测试结果没有任何问题,以上就是工厂模式,抽象工厂模式,如果各位猿友有想要交流的可以留言,如果觉得我哪里说的不对,或者说有更准确的说法都可以说,不过因为白天上班比较忙,所以一般到晚上才能统一回复,希望这边文章在帮助我自我提升的同时也能帮助各位猿友。