工厂方法模式共分为三种:普通工厂模式,静态工厂模式,抽象工厂模式
1、普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先请看下关系图。
举例如下:(我们举一个发送邮件和短信的例子)
首先,创建二者的共同接口:
//1.首先写一个接口
public interface Sender {
//不用加abstract关键字,在这里默认就是抽象方法
public void send();
}
//2.1紧接着创建两个实现接口1
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("send sms");
}
}
//2.2紧接着创建两个实现接口2
public class MailSender implements Sender {
@Override
public void send() {
System.out.println("send mail");
}
}
//3.创建工厂类
public class SendFactory {
//生产方法生产产品,由于还不知道生产的是什么产品,所有用大的父类Sender来接收
//到底生产的产品是什么由传入的参数决定
public Sender produce(String name){
if("sms".equals(name)){
return new SmsSender();
}else if("mail".equals(name)){
return new MailSender();
}else{
System.out.println("无法生产此产品");
return null;
}
}
}
//创建测试类
public class TestFactoryDemo {
public static void main(String[] args) {
//1.通过工厂来创建对象
SendFactory sf = new SendFactory();
//2.调用工厂的生产方法,生产对象
Sender s = sf.produce("sms"); //此方法返回的是Sender的一个子类
s.send(); //调用父类的方法,如果子类重写了父类的方法,父类的引用只能调用子类重写的方法(多态)
//也就是说上面传入的哪个子类的参数我们就调用哪个子类的方法
}
}
/
2、静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。
如果向调用的工厂方法中随意的传值的话,可能会造成空指针异常,那么怎么处理呢?
//修改完善TestFactoryDemo,避免用户随意输入造成的空指针异常
public class TestFactoryDemo {
public static void main(String[] args) {
//1.通过工厂来创建对象
// SendFactory sf = new SendFactory();
//2.调用工厂的生产方法,生产对象
// Sender s = sf.produce();
// s.send();
//完善工厂类,使其避免null指针(设计的结构上)
//在工厂类中分别给不同的产品创建不同的方法,不让用户输入
//为了可以使用SendFactory直接调用方法,我们可以将SendFactory中的方法加static直接提升为静态方法
Sender sms = SendFactory.produceSms();
sms.send();
}
}
//修改SendFactory类,不让用户输入
//将一个方法拆成两个方法,这时在TestFactoryDemo类中用户想创建哪个调用哪个方法就不会报错了.
public class SendFactory {
//生产产品
/*public Sender produce(String name){
if("sms".equals(name)){
return new SmsSender();
}else if("mail".equals(name)){
return new MailSender();
}else{
System.out.println("无法生产此产品");
return null;
}
}*/
//加static提升为静态方法,方便直接使用类名.调用静态方法
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
3、抽象工厂模式(Abstract Factory)
工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了开闭原则(即:对扩展开发,对修改关闭。在程序的需求发生变化的时候,不能去修改源代码,而是去扩展新的功能模块,实现热插拔的效果。),所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。因为抽象工厂不太好理解,我们先看看图,然后就和代码,就比较容易理解。
//创建一个接口,强制要求每个工厂都具有生产能力
public interface Provider {
//规范,要求工厂都具备的生产能力
//Sender是所有产品的父类
public Sender produce();
}
//实现Provider接口
public class MailSenderFactory implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
//实现Provider接口
public class SmsSenderFactory implements Provider {
@Override
public Sender produce() {
return new SmsSender();
}
}
//调用对象
import java.util.ResourceBundle;
public class TestFactoryDemo {
public static void main(String[] args) throws Exception {
//资源句柄,读取java配置文件中的资源数据的
ResourceBundle rb = ResourceBundle.getBundle("xxx.xxx.finallyfactory.config");//读取配置文件的方式
String str = rb.getString("factoryInfo");
System.out.println(str);
//1.创建工厂对象
Class factoryClass = Class.forName(str);//反射的方式
Provider factory = (Provider) factoryClass.newInstance();
//2.生产产品
Sender sender = factory.produce();
sender.send();
}
}
//配置文件资源
//config.properties
factoryInfo=xdl.day23.finallyfactory.SmsSenderFactory
工厂设计模式总结
工厂接口
具体的工厂1
具体的工厂2
商品接口
具体的商品接口1
具体的商品接口2
测试类
创建具体的工厂对象
使用工厂对象创建商品对象