Java设计模式(2)创建型:工厂模式(工厂方法模式与抽象工厂模式)

时间:2022-10-02 18:57:42

工厂模式属于创建型设计模式,包括工厂方法模式和抽象工厂模式。凡是出现了大量的对象需要创建,并且具有共同的接口时,都可以通过工厂模式进行创建,本篇将同时介绍这两种创建型模式。


(一)工厂方法模式

工厂方法模式常见有3种编码写法,以发送邮件和SMS信息业务为例分别介绍:

1)第一种编码写法,也常被称为简单工厂模式,表现方式是通过传参来确认工厂创建对象的类型。

发送器接口,定义发送方法:

public interface ISender {
public void Send();
}
邮件发送器实现接口

public class MailSender implements ISender {
@Override
public void Send() {
System.out.println("this is mailsender!");
}
}
SMS信息发送器实现接口

public class SmsSender implements ISender{
@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
发送器生成工厂

public class SendFactory {
public ISender produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
} else {
System.out.println("请输入正确的类型!");
return null;
}
}
}
执行代码:

SendFactory factory = new SendFactory();
ISender sender = factory.produce("mail");
sender.Send();
(注)简单工厂模式并不满足开闭原则,客户端使用时必须知道创建的类型,否则有可能会因为传参错误导致创建失败。

2)第二种编码写法,是在简单工厂模式的情况下改进,将传参创建的方式改为方法直接创建。

将SendFactory工厂类修改为:

public class SendFactory {
public ISender produceMail() {
return new MailSender();
}
public ISender produceSms() {
return new SmsSender();
}
}
执行代码:

SendFactory factory = new SendFactory();
ISender sender = factory.produceMail();
sender.Send();
(注)这种写法改善了简单工厂模式的传参创建方式,但缺点是需要实例化工厂类。

3)第三种编码写法,也叫静态工厂模式,主要表现方式为创建对象时不需要实例化工厂类。
SendFactory工厂类修改为:

public class SendFactory {
public static ISender produceMail() {
return new MailSender();
}
public static ISender produceSms() {
return new SmsSender();
}
}
执行代码:

ISender sender = SendFactory.produceMail();  
sender.Send();

这三种写法各有利弊,但最后一种是更为常用的写法。


(二)抽象工厂模式

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了开闭原则。从设计角度考虑,抽象工厂模式可以很好解决这个问题。

抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例,换言之,也就是这些抽象产品的具体子类的实例。
(注)接口ISender、类MailSender和类SmsSender与简单工厂模式的代码一致,此例不再贴出。

IProvider工厂创建接口:

public interface IProvider {
public ISender produce();
}
SendMailFactory工厂类实现接口:

public class SendMailFactory implements IProvider{
@Override
public ISender produce() {
// TODO 自动生成的方法存根
return new MailSender();
}
}
SendMsmFactory工厂类实现接口:

public class SendMsmFactory implements IProvider {
@Override
public ISender produce() {
// TODO 自动生成的方法存根
return new SmsSender();
}
}
执行代码:

IProvider provider = new SendMailFactory();
ISender sender = provider.produce();
sender.Send();
运行结果:this is mailsender!

(注)抽象工厂模式满足开闭原则,如果扩展创建类型如IMessage,只需创建SendIMessageFactory工厂类并实现相关接口即可,无需修改已有的代码。