工厂模式的实现

工厂模式是一种设计思想,它适用于需要创建多个具体实例的场景,并且这些实例都具有一个共同的方法(动作)。比如,“发送信息”。我们都知道,发送信息的方式有很多种,但无论是用微信发送,还是用邮件发送,它们都有一个共同的动作,就是“发送”,那么可以把这个动作(send)抽象出来。
1.普通工厂模式
抽象的动作:

package com.itant.pattern.sender;
public interface Sender {
	void send();
}

具体的实现:

package com.itant.pattern.sender;
public class EmailSender implements Sender {

	@Override
	public void send() {
		System.out.println("用邮件发送");
	}
}
package com.itant.pattern.sender;
public class WechatSender implements Sender {
	
	@Override
	public void send() {
		System.out.println("用微信发送");
	}
}

经过以上的步骤,发送的动作有了,还差一个“工厂”来生成这些具体的发送动作:

package com.itant.pattern;

import com.itant.pattern.sender.EmailSender;
import com.itant.pattern.sender.Sender;
import com.itant.pattern.sender.WechatSender;

public class CommonFactory {
	public Sender generateSender(String type) {
		if (type.equals("email")) {
			return new EmailSender();
		} else if (type.equals("wechat")) {
			return new WechatSender();
		} else {
			return null;
		}
	}
}

测试:

package com.itant.pattern;
import com.itant.pattern.sender.Sender;

public class Test {

	public static void main(String[] args) {
		// 普通工厂模式
		CommonFactory commonFactory = new CommonFactory();
		
		Sender wechatSender = commonFactory.generateSender("wechat");
		wechatSender.send();
		
		Sender emailSender = commonFactory.generateSender("email");
		emailSender.send();
	}
}

2.多个工厂方法模式
以上的普通工厂模式有个缺点,就是参数传错了的话,可能返回的Sender会为null,引起空指针异常等情况,虽然可以做一些判断去“补救”,但这样的设计是有缺陷的,不建议在设计的时候用,要想规避这种情况,那么我们就不要传参了,直接使用指定的方法生成指定的Sender即可,我们改造一下Factory:

package com.itant.pattern;

import com.itant.pattern.sender.EmailSender;
import com.itant.pattern.sender.Sender;
import com.itant.pattern.sender.WechatSender;

public class MultiFactory {
	public Sender generateWechatSender() {
		return new WechatSender();
	}
	
	public Sender generateEmailSender() {
		return new EmailSender();
	}
}

测试:

package com.itant.pattern;
import com.itant.pattern.sender.Sender;

public class Test {

	public static void main(String[] args) {
		
		MultiFactory multiFactory = new MultiFactory();
		Sender wechatSender = multiFactory.generateWechatSender();
		wechatSender.send();
		
		Sender emailSender = multiFactory.generateEmailSender();
		emailSender.send();
	}
}

这样确实是可以避免参数传错的情况了,但我们可以进一步优化,在多个工厂方法模式的基础上进行优化,于是引入静态工厂模式。

3.静态工厂模式
同样是改造Factory,在多个工厂方法模式的基础上,把方法改成static的,这样就可以省略实例化工厂的步骤:

package com.itant.pattern;

import com.itant.pattern.sender.EmailSender;
import com.itant.pattern.sender.Sender;
import com.itant.pattern.sender.WechatSender;

public class StaticFactory {
	public static Sender generateWechatSender() {
		return new WechatSender();
	}
	
	public static Sender generateEmailSender() {
		return new EmailSender();
	}
}

测试:

package com.itant.pattern;
import com.itant.pattern.sender.Sender;

public class Test {

	public static void main(String[] args) {
		Sender wechatSender = StaticFactory.generateWechatSender();
		wechatSender.send();
		
		Sender emailSender = StaticFactory.generateEmailSender();
		emailSender.send();
	}
}

好的,目前为止,似乎一切还不错,大多数情况下,使用静态工厂模式即可,因为它确实是满足开发需求的,而且也比较简洁清晰。但是有一个问题就是,每次有新的实例都要修改我们的工厂类,例如有一天,新增了一个发送方式–“QQSender”,这个时候,我们必然要修改StaticFactory,新增一个generateQQSender()的方法,这样是违背了设计模式的“开闭原则”的,即:我们希望对扩展开放,对修改关闭。于是引入终极的抽象工厂模式:

4.抽象工厂模式
抽象工厂模式同样是对工厂进行改造。最开始的时候,我们就对“发送”这个动作进行了抽象,举一反三,我们同样也可以对工厂频繁“生产”这个动作进行抽象:

package com.itant.pattern.factory;

import com.itant.pattern.sender.Sender;

public interface Factory {
	Sender generateSender();
}

然后我们需要什么样具体的工厂的话就可以自行扩展:

package com.itant.pattern.factory;

import com.itant.pattern.sender.Sender;
import com.itant.pattern.sender.WechatSender;

public class WechatFactory implements Factory {

	@Override
	public Sender generateSender() {
		// TODO Auto-generated method stub
		return new WechatSender();
	}
}
package com.itant.pattern.factory;

import com.itant.pattern.sender.EmailSender;
import com.itant.pattern.sender.Sender;

public class EmailFactory implements Factory {

	@Override
	public Sender generateSender() {
		// TODO Auto-generated method stub
		return new EmailSender();
	}
}

测试:

package com.itant.pattern;

import com.itant.pattern.factory.EmailFactory;
import com.itant.pattern.factory.Factory;
import com.itant.pattern.factory.WechatFactory;
import com.itant.pattern.sender.Sender;

public class Test {
	public static void main(String[] args) {
		Factory wechatFactory = new WechatFactory();
		Sender wechatSender = wechatFactory.generateSender();
		wechatSender.send();
		
		Factory emailFactory = new EmailFactory();
		Sender emailSender = emailFactory.generateSender();
		emailSender.send();
	}
}

这样,我们就得到了相对比较完整的工厂模式。抽象工厂模式适用于某种动作有多种实现方式(某种操作有多种实现方案)的情况,扩展方便、灵活,如果非要说缺点,就是工厂类的增加,每新增一种操作,都需要新增一个对应的工厂类,在简单的项目中似乎显得冗余,但是在复杂的项目中则可以让条理非常清晰,所以,在实际使用过程中,可以针对项目的复杂情况而采用相应的工厂模式,在简单的小项目中,可以直接使用静态工厂模式,在复杂的项目中,推荐使用抽象工厂模式。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ithouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值