Java设计模式
创建模式
Factory(工厂模式)
- 简单的Factory实例
- 多Factory实例
- 静态的实例
- 抽象工厂实例
Factory简介
工厂设计模式,就是通过工厂类产生某些具有相同特性的类的实例,在这里相同的特性是指这些类都实现了同一个接口。
下面我们将通过一些实例来学习Factory。
简单工厂模式
假定一个代码场景,发送邮件或短信。首先我们要创建一个Sender通用接口:
/*
* 创建一个发送类
* */
public interface Sender {
public void Send();
}
接着我们创建两个实现Sender接口的类,发送邮件类mailSender,发送短信的类smsSender。
/*
* 发送邮件的类,实现Sender接口
* */
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("I'm mailSender!");
}
}
/*
* 发送短信的类,实现Sender接口
* */
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("I'm SmsSender!");
}
}
创建一个工厂类,来生成MailSender和SmsSender类的对象:
/*
* 生成MailSender和SmsSender的对象
* */
public class SendFactory {
//返回Sender对象
public Sender produce(String type){
if("mail".equals(type)){
//MailSender对象
return new MailSender();
}else if("sms".equals(type)){
//SmsSender对象
return new SmsSender();
}else{
System.out.println("请输入正确的类型!");
return null;
}
}
}
测试工厂类
/*
* 测试工厂类*/
public class FactoryTest {
public static void main(String[] args){
//生成工厂类的对象
SendFactory factory = new SendFactory();
//利用factory对象的produce方法生成Sender对象
Sender smsSender = factory.produce("sms");
smsSender.Send();
//利用factory对象的produce方法生成Sender对象
Sender mailSender = factory.produce("mail");
mailSender.Send();
}
}
测试输出
I’m SmsSender!
I’m mailSender!
通过上面这个简单的实例,我们应该大概明白了,Factory设计模式的重要思想:
1.接口 – Sender
2.实现接口的类 – MailSender SmsSender
3.产生这些类实例对象的工厂类 – SendFactory
多个工厂方法
上面的识别中我们可以看到SendFactory 类中的produce必须传递参数,否则不能够进行区分到底是创建SmsSender对象还是MailSender对象。如果不传参数,我们可以创建多个produce方法来实现区分。
/*
* 创建多个produce方法*/
public class MultiSendFactory {
//创建produceMail
public Sender produceMail(){
return new MailSender();
}
//创建produceSms
public Sender produceSms(){
return new SmsSender();
}
}
测试类
/*
* 测试使用不同的produce方法创建对象
* */
public class MultiFactoryTest {
public static void main(String[] args){
MultiSendFactory multiFactory = new MultiSendFactory();
Sender smssender = multiFactory.produceSms();
smssender.Send();
Sender mailsender = multiFactory.produceMail();
mailsender.Send();
}
}
测试结果:
I’m SmsSender!
I’m mailSender!
上面的修改只是将工厂类中的创建类的实例进行了修改,没有其他很大的影响。能懂就成。
静态工厂方法模式
在上面的测试类中,我们都是先创建了工厂类的实例,再通过实例调用方法,返回实现接口类的实例。如果我们想省略掉创建工厂类实例这步的话,我们可以将Factory类中的创建实例方法直接声明为静态方法,通过类名.方法名直接调用。
/*声明为静态方法*/
public class StaticSendFactory {
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
测试类:
public class StaticFactoryTest {
public static void main(String[] args){
//不创建factory对象,直接通过classname.methodname调用
Sender mailSender = StaticSendFactory.produceMail();
mailSender.Send();
Sender smsSender = StaticSendFactory.produceSms();
smsSender.Send();
}
}
测试结果:
I’m mailSender!
I’m SmsSender!
上面的示例主要是展示了通过调用工厂类的静态方法来实现创建类的实例。
抽象工厂模式
大家想一个问题,现在我们实现了发送邮件、短信的工厂类,如果我们想增加一个发送QQ消息的类,那么我们要通过Factory类获取发送QQ消息类的对象,是不是又要在Factory类里面增加代码,让它能够new 一个QQ消息类的发送对象,这样的话就违背了开闭原则,对扩展开发,对修改关闭。如果我们直接新增一个创建QQ消息的工厂类,创建发送QQ消息对象,这样不需要修改之前的代码。
Sender类,SmsSender、MailSender类保持不变,我们只对Factory类进行修改,创建不同的工厂类。
/*
* 创建mail的工厂类
* */
public class SendMailFactory implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
/*
* 创建SMS的工厂类
* */
public class SendSmsFactory implements Provider {
@Override
public Sender produce() {
return new SmsSender();
}
}
工厂类的接口provider
/*
工厂类的通用接口
* */
public interface Provider {
public Sender produce();
}
测试方法:
/*
*每个类有自己的工厂类
* */
public class AbstractFactoryTest {
public static void main(String[] args){
Provider smsProvider = new SendMailFactory();
Sender smsSender = smsProvider.produce();
smsSender.Send();
Provider mailProvider = new SendSmsFactory();
Sender mailSender = mailProvider.produce();
mailSender.Send();
}
}
输出结果:
I’m mailSender!
I’m SmsSender!
接着我们上面所讲的,如果新增一个QqSender,新建一个SendQqFactory类,这个类继承自抽象接口Provider,并实现produce方法。这种方式的好处是当有新功能增加时,不需要修改现有的代码,而是直接新增实现类,实现Sender接口,新增一个工厂类,实现Provider接口。很明显这样做,拓展性比较好。
抽象工厂模式主要包含:
抽象接口A,A实现类若干,
工厂类若干,工厂类的抽象类B