工厂模式
作用
实现了创建者和调用者分离
核心本质
- 实例化对象不用new,用工厂替代
- 将选择实现类,创建对象统一管理和控制,从而将调用者跟我妈的实现者解耦
一、简单工厂模式(静态工厂模式)
public interface Car{
void name();
}
public class WuLing implements Car{
@Override
public void name() {
System.out.println("五菱宏光!");
}
}
public class Tesla implements Car{
@Override
public void name() {
System.out.println("特斯拉!");
}
}
public class CarFactory {
public static Car getCar(String car){
if (car.equals("五菱")){
return new WuLing();
} else if (car.equals("特斯拉")){
return new Tesla();
} else {
return null;
}
}
}
public class Consumer {
public static void main(String[] args) {
/*传统方式:
接口,所有的实现类
Car car = new WuLing();
Car car2 = new Tesla();
* */
//使用工厂创建
Car car1 = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("特斯拉");
car1.name();
car2.name();
}
}
有个小弊端:没有开闭原则 (想重新加入一辆车的时候,必须修改工厂的源代码)
但是大多数情况下,我们都是使用这种简单工厂模式,要满足开闭原则,会付出很多代价(如:工厂方法模式)
二、工厂方法模式
需要把工厂类改为:工厂接口和工厂实现类(加一层来解决问题)
/*工厂方法模式
* 创建多个工厂
* 多个工厂都实现了共同的接口
* */
public interface CarFactory {
Car getCar();
}
//五菱工厂
public class WuLingFactory implements CarFactory{
@Override
public Car getCar() {
return new WuLing();
}
}
//特斯拉工厂
public class TeslaFactory implements CarFactory{
@Override
public Car getCar() {
return new Tesla();
}
}
消费者要买什么车就new什么工厂
//消费者
public class Consumer {
public static void main(String[] args) {
Car car = new WuLingFactory().getCar();
Car car2 = new TeslaFactory().getCar();
car.name();
car2.name();
Car car3 = new MoBaiFactory().getCar();
car3.name();
}
}
通过这个方法增加任何产品都不会影响原有代码,但是每增加一个产品就对应一个工厂类,越来越多就会极其庞大。
抽象工厂模式
假设有非常多的车,比如:Car里边有非常多零件,要设计很多接口
普通的工厂模式解决不了了,延伸出了抽象工厂模式
大工厂
//生产各类产品的大工厂
public interface ProducingFactory {
IPhoneProduct producingPhone(); // 生产手机
IRouterProduct producingRouter(); // 生产路由器
}
工厂实现类
//华为工厂 可以生产华为手机与华为路由器
public class HuaweiFactory implements ProducingFactory {
@Override
public IPhoneProduct producingPhone() {
return new HuaweiPhone();
}
@Override
public IRouterProduct producingRouter() {
return new HuaweiRouter();
}
}
//小米工厂 可以生产小米手机与小米路由器
public class XiaomiFactory implements ProducingFactory {
@Override
public IPhoneProduct producingPhone() {
return new XiaomiPhone();
}
@Override
public IRouterProduct producingRouter() {
return new XiaomiRouter();
}
}
产品1接口
//手机产品接口
public interface IPhoneProduct {
void start();
void end();
void call();
void sendMessage();
}
产品1接口实现类
//华为手机产品
public class HuaweiPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("华为手机开机");
}
@Override
public void end() {
System.out.println("华为手机关机");
}
@Override
public void call() {
System.out.println("华为手机打电话");
}
@Override
public void sendMessage() {
System.out.println("华为手机发短信");
}
}
测试方法:
public static void main(String[] args) {
//华为系列产品
HuaweiFactory huaweiFactory = new HuaweiFactory();
IPhoneProduct huaweiPhone = huaweiFactory.producingPhone();
huaweiPhone.call();
IRouterProduct huaweiRouter = huaweiFactory.producingRouter();
huaweiRouter.openNet();
//小米系列产品
XiaomiFactory xiaomiFactory = new XiaomiFactory();
IPhoneProduct xiaomiPhone = xiaomiFactory.producingPhone();
xiaomiPhone.call();
IRouterProduct xiaomiRouter = xiaomiFactory.producingRouter();
xiaomiRouter.openNet();
}
类图
优点
- 厂商可以将一个系列的产品放到一起创建
- 调用者无需关心产品的创建过程细节,只需要获取工厂即可
缺点
- 如果要生产更多的产品就必须要改动大工厂,厂商也需改动,产品集合被固定了
- 增加系统抽象性,更难以理解
应用场景
- JDK中Calendar的getlInstance方法
- JDBC中的Connection对象的获取
- Spring中IOC容器创建管理bean对象
- 反射中Class对象的newInstance方法