普通工厂模式
概念
普通工厂方法模式就是建立一个工厂类,对实现了同一接口的不同实现类进行实例的创建。实际上就是new对象
类图
右侧一个接口(Sender)两个实现类(MailSender、SmsSender),左侧工厂类(SendFactory)produce方法有一个String类型的参数type,返回值为Sender(构成多态)。代码如下:
Sender
public interface Sender {
// 自定义抽象方法
void send();
}
MailSender
public class MailSender implements Sender {
@Override
public void send() {
System.out.println("正在发送邮件!!");
}
}
SmsSender
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("正在发送短信!!");
}
}
SendFactory
public class SendFactory {
// 自定义成员方法实现对象的创建
public Sender produce(String type){
if("mail".equals(type)){
return new MailSender();
}
if("sms".equals(type)){
return new SmsSender();
}
return null;
}
}
测试类SendFactoryTest 及优缺点说明
public class SendFactoryTest {
public static void main(String[] args) {
// 优点:扩展性和可维护性更强! 尤其是在创建大量对象的前提下
// 缺点:代码略复杂,可读性略差
// 最主要的缺点在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,并且可能出现空指针异常。
// 1.声明工厂类类型的引用指工厂类类型的对象
SendFactory sf = new SendFactory();
// 2.调用生产方法来实现对象的创建
Sender sender = sf.produce("mail");
// 3.使用对调用方法模拟发生的行为
sender.send();
System.out.println("-----------------------------------------");
/*
// 优点:代码简单,可读性强 在创建单个对象时有优势
// 缺点:扩展性和可维护性略差
Sender sender1 = new MailSender();
sender1.send();
*/
}
}
运行结果:
对普通工厂类可能出现空指针异常的缺点,我们做出了一个改进:多个工厂方法模式
多个工厂方法模式
多个工厂模式与普通工厂模式在类图上可以看出,主要的不同就是普通工厂模式是一个方法创建多个对象,多个工厂模式变成了 两个方法各自创建自己的对象。
public class SendFactory {
// 缺点:在多个工厂方法模式中,为了能够正确创建对象,先需要创建工厂类的对象才能调用工厂类中的生产方法。
// 就是说需要在main()方法里面创建SendFactory这个类型的对象,才可以调用
public Sender produceSms(){
return new SmsSender();
}
public Sender produceMail(){
return new MailSender();
}
}
这样,就可以解决因为传字符串参数出错导致的空指针问题了。但是还是有一些问题,我们继续优化。
在代码块中我们已经提到了该方法的缺点,就是在调用方法的时候我们还需要先new()一个工厂类的对象才可以调用它的方法,解决办法当然有,而且还很简单。我们只需要把方法提升到类层级,使方法可以通过 类名. 的方式调用就可以了,也就是说,给每一个方法加上static关键字修饰,变成:静态工厂方法模式
静态工厂方法模式
SendFactory
public class SendFactory {
public static Sender produceSms(){
return new SmsSender();
}
public static Sender produceMail(){
return new MailSender();
}
}
SendFactoryTest
public class SendFactoryTest {
public static void main(String[] args) {
SendFactory.produceMail();
SendFactory.produceSms();
}
}
至此,我们已经得到了很优秀的工厂方法模式的代码。
工厂方法模式的实际意义
工厂方法模式适合:凡是出现了大量的产品(对象)需要创建,且拥有共同的接口的时候,可以通过工厂方法模式进行创建。
工厂方法模式的主要缺点
类的创建依赖于工厂类,也就是说,如果需要拓展新的业务,生产新的产品,就必须去修改工厂的类代码。我们学习设计模式的时候讲到过,要遵循的开闭原则,在这里并没有实现。所以还存在一定的问题,并没有做到对修改关闭。这里我们提出了另一个模式。。。
抽象工厂模式
从类图中不难看出抽象工厂模式与之前的工厂模式的区别,我们直接来看代码:
Provider
public interface Provider {
// 自定义抽象方法描述产品的生产
Sender produce();
}
MailSendFactory
public class MailSendFactory implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
SmsSendFactory
public class SmsSendFactory implements Provider {
@Override
public Sender produce() {
return new SmsSender();
}
}
SendFactoryTest
public class SendFactoryTest {
public static void main(String[] args) {
Provider provider = new MailSendFactory();
Sender sender1 = provider.produce();
sender1.send();
provider = new SmsSendFactory();
Sender sender2 = provider.produce();
sender2.send();
}
}
结果:
优点说明:
我们说抽象工厂模式解决了上面几个工厂模式没有实现的开闭原则,如果需要拓展新的业务,生产新的产品,使用抽象工厂模式就只需要增加一个类并且让这个类实现Provider这个接口就可以了,又得到了扩展,有没有修改原有的代码,对工厂模式来说简直完美!
到此,工厂模式学习完毕。
本文章只是个人学习,内容不多,也都很基础,如果内容上有什么问题,还请大家多多指教!!
一定会有那么一天,我也能用上这句话:“本性闲散,最终却也跟上了前辈的步伐”