概述
工厂,就是生产产品的地方。在Java设计模式中使用工厂的概念,那就是生成对象的地方了。本来直接就能创建的对象为何要增加一个工厂类呢?
这就需要了解工厂方法要解决的是什么问题了,如果只有一个类,我们直接new一个对象完事,这是最简单的;但是如果有多个类呢,而且这些类还需要针对不同的情况来创建不同的对象,这时候就需要工厂了,我们可以在工厂中根据条件来创建具体的对象。这样一来就将调用方和具体的目标类进行了解耦,调用方根本就不知道需要创建那个对象,它只是提出了条件,然后工厂就可以根据给定的条件来决定创建哪一个对象。
举个栗子:
假如有个厂商代生产手机,它当前可以生产华为手机,随着业务的扩展,这个代工厂还要生产小米和OPPO手机,这样我们就需要一个类去生产这些手机,这就用到了简单工厂模式。接下来我们先看一下简单工厂模式的实现。
简单工厂模式
我们创建一个计算机的抽象产品类,其中有一个抽象方法用于启动手机,如下所示。
public abstract class Phone {
//产品的抽象方法,由具体的产品类实现
public abstract void product();
}
接着我们创建各个品牌的手机,都继承了自己的父类Phone,并实现了父类的product方法。
public class HUAWEIPhone extends Phone {
@Override
public void product() {
System.out.println("生产华为手机");
}
}
public class OPPOPhone extends Phone {
@Override
public void product() {
System.out.println("生产OPPO手机");
}
}
public class XiaoMiPhone extends Phone {
@Override
public void product() {
System.out.println("生产小米手机");
}
}
工厂类
public class PhoneFactory {
public static Phone productPhone(String type) {
Phone mPhone = null;
switch (type) {
case "huwei":
mPhone = new HUAWEIPhone();
break;
case "oppo":
mPhone = new OPPOPhone();
break;
case "xiaomi":
mPhone = new XiaoMiPhone();
break;
}
return mPhone;
}
}
客户端调用工厂类
public class ProductPhone {
public static void main(String[] args) {
PhoneFactory.productPhone("huawei").product();
}
}
使用简单工厂模式的场景和优缺点
- 使用场景
- 工厂类负责创建对象比较少
- 客户只需要知道传入工厂类的参数,而无需关系创建对象的逻辑。
- 优点:使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性。
- 缺点:可实例化的类型在编译期间已经被确定。如果增加新类型,则需要修改工厂,这违背了开放封闭原则。简单工厂需要知道所有要生成的类型,其当子类过多或者子类层次过多时不适合使用。
工厂方法模式
定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到子类。
创建抽象工厂
抽象工厂创建一个方法来生产各种手机
public abstract class PhoneFactory {
public abstract <T extends Phone> T productPhone(Class<T> clz);
}
具体工厂
海外代工厂是一个具体的工厂,其继承抽象工厂,通过反射来生产不同厂家的手机
public class HWPhoneFactory extends PhoneFactory {
@Override
public <T extends Phone> T productPhone(Class<T> clz) {
Phone mPhone = null;
String className = clz.getName();
try {
//通过反射来生产不同厂家的手机
mPhone = (Phone) Class.forName(className).newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
客户端调用
public class Client {
public static void main(String[] args) {
PhoneFactory mPhoneFactory = new HWPhoneFactory();
HUAWEIPhone mHUAWEIPhone = mPhoneFactory.productPhone(HUAWEIPhone.class);
mHUAWEIPhone.product();
OPPOPhone mOPPOPhone = mPhoneFactory.productPhone(OPPOPhone.class);
mOPPOPhone.product();
XiaoMiPhone mXiaoMiPhone = mPhoneFactory.productPhone(XiaoMiPhone.class);
mXiaoMiPhone.product();
}
}
总结:
对于简单工厂模式,我们都知道其在工厂类中包含了必要的逻辑判断,根据不同的条件来动态实例化相关的类。对客户端来说,这去除了具体产品的依赖;但与此同时也会带来一个问题:如果我们要增加产品,比如我们要生产苹果手机,就需要在工厂模式类中添加一个case分支条件,这违背了开放封闭原则,对修改也开放了。而工厂方法模式就没有违背这个开放封闭原则。如果我们需要生产苹果手机,则无需修改工厂类,直接创建产品即可。