从买车到工厂设计模式(三件套)

701 阅读7分钟

上文回顾:

简单工厂模式链接:juejin.cn/post/684490…

简单工厂模式核心代码:

public class CarFactory {
	
	public Car getCar(String name){
		if("Porsche".endsWith(name)){
			return new PorscheCar();
		}
		else if("Bugatti".endsWith(name)){
			return new BugattiCar();
		}
		return new PorscheCar();
	
	}
	
}

同时,和我们之前系列文章不止一次的强调的那样,如果把要维护对象的数量提升到一个很高的量级,即我们简单工厂模式需要维护成千上万的对象,那么我们程序肯定会爆炸的。

这么一想,的确是这样,当维护对象比较多的时候确实会比较麻烦,所以天才的科学家们呢肯定不会放任这个问题坐视不管的,于是简单工厂模式plus升级版本诞生了,不过我个人感觉工厂方法模式并没有解决最本质的问题,可以说是换汤不换药,披着工厂方法模式的单例模式。

我刚才说了什么?工厂方法模式?我想起来了,今天要写工厂方法模式。

合着你刚才说半天都不知道要写啥啊?!

走,走,让你来说相声来了?

对,我们下面来看工厂方法模式

工厂方法模式定义:

工厂方法模式是简单工厂的进一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。

这里就不设什么微剧场了,我相信天才的读者们看到代码就自然了解了。

应用场景:

  • 客户端不知道要创建出来的类是什么,但是知道对应的工厂是什么。
  • 客户端可以通过子类来指定创建对应的对象

代码实战:

我们在原来简单工厂模式实例的基础上,新增一个Factory接口类,用于规范我们工厂的行为。

public interface Factory {
	
	public Car getCar();

}

然后编写他们的相关实现:

//布加迪
public class BugattiFactory implements Factory {

	@Override
	public Car getCar() {
		// TODO Auto-generated method stub
		return new BugattiCar();
	}

}
//保时捷
public class PorscheFactory implements Factory{

	@Override
	public Car getCar() {
		// TODO Auto-generated method stub
		return new PorscheCar();
	}

}


测试:

public class Test {
	
	public static void main(String[] args) {

		Factory bugattiFactory  = new BugattiFactory();
		Car car = bugattiFactory.getCar();
		car.description();
		
		Factory porschFactory = new PorscheFactory();
		car = porschFactory.getCar();
		car.description();
	}

}

输出:

布加迪跑车
保时捷汽车

这..这..这看起来有点像那个什么,那个什么来着,单例,单例模式?

的确是有点像的,确实在设计模式里面有很多模式之间是运作流程是有点类似的,这点在代理模式和装饰者模式之间的争论有所提及,感兴趣的朋友可以看一下我的那篇笔记。

当然,工厂模式这么看起来确实是有点尴尬了,原来一个工厂造所有车,但是型号多了维护不过来,现在是每一个型号都建了一个单独的工厂生产,这么一来型号多了工厂就会变得有点多,万一我同时买个十几种不同型号的车,那岂不是要跑去十多个工厂?太累了,不行,不行,难道就没有更好的方法了吗?

叮叮叮叮,当当当当

抽象工厂模式!(请读者自行脑补哆啦A梦的语气)。

抽象工厂模式:

**抽象工厂模式(**Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

工厂模式发展到抽象工厂模式,才真的有点设计模式家族的样子,抽象工厂设计模式在工厂模式上再加一层,做一个超级工厂,从超级工厂获取工厂,然后在从工厂中获取具体的对象。

头有点晕,不废话,码上看代码

等等,我刚才说了什么?码上?欢迎关注本人或本人的java技术博客【码上】jdkcb.com 码上开始行动!

广告,滚。

在看代码前我们先来说一下抽象工厂模式的应用场景:

  • 和工厂方法一样客户端不需要知道它所创建的对象的类
  • 需要一组对象共同完成某种功能时。并且可能存在多组对象完成不同功能的情况。
  • 代码结构稳定,不需要频繁修改和扩展产品功能。

应用实例:

  • 王者荣耀换皮肤,一次换一套
  • QQ秀换皮肤,一套一次换
  • 英雄联盟换皮肤,换一套一次

官方吐槽:除了换皮肤你就不能换点别的????!!

不能

代码实战

现在我们让客户的需求更加刁钻一些,客户现在需要不同的颜色的法拉利跑车。

首先声明一个Color接口类,用于规范我们颜色的行为。

public interface Color {
   void name();
}

编写相关的实现

public class Red implements Color{

	@Override
	public void name() {
		System.out.println("是红色的");
	}

}

public class Blue implements Color{

	@Override
	public void name() {
		System.out.println("是蓝色的");
		
	}

}


然后创建我们的抽象工厂类:

public abstract class Factory {
	public abstract void getCar();
	public abstract void getColor();
	

}

编写相关实现:

//红色法拉利
public class RedPorscheFactory extends Factory {

	@Override
	public Car getCar() {
		// TODO Auto-generated method stub
		return new PorscheCar();
	}

	@Override
	public Color getColor() {
		// TODO Auto-generated method stub
		return new Red();
	}


}

//蓝色布加迪
public class BlueBugattiFactory extends Factory {

	@Override
	public Car getCar() {
		// TODO Auto-generated method stub
		return new BugattiCar();
	}

	@Override
	public Color getColor() {
		// TODO Auto-generated method stub
		return new Blue();
	}

}



最后为了体现超级工厂这个概念,我们新增一个超级工厂类,当然部分场景下是需要的,本例属于可有可无的范围。

public class BigFactory {
	
	public static Factory getFactory(String name){
		if("bugatti".endsWith(name)){
			return new BlueBugattiFactory();
		}else if("porsche".endsWith(name)){
			return new RedPorscheFactory();
		}
		return null;
		
	}

}

测试:

public class Test {
	
	public static void main(String[] args) {
		Factory factory = BigFactory.getFactory("bugatti");
		Car car  = factory.getCar();
		Color color = factory.getColor();
		car.description();
		color.name();
	}

}

输出:

布加迪跑车
是蓝色的

由此可见,抽象工厂模式维护的是一套对象,那么什么时候会用到抽象工厂模式呢?

王者荣耀换皮肤的时候。

大家想,王者荣耀英雄换皮肤的时候,是不是一换一整套,这不就像当我们的产品需要向多个不同操作平台适配的时候,而编写相应的一套实现。比如面向liunx的叫linuxFactory,面向win的叫winFactory等等。

这个时候,有的读者可能会想到,是不是有点像模板设计模式,不尽然,虽然两者在职责上有重叠的部分,都是根据不同情况相应地提供不同实现,但是实现方式却不一样,工厂模式不关心是那个类具体实现了Car接口,也不关心是哪个实体类代表了法拉利,获取这个类的途径是通过工厂获取,使用者只需要知道对应的工厂是什么,而完全不需要care相关细节。

所以说呢,设计模式学到最后往往就可以把握到万千设计模式中那不变的一部分,因为工厂方法模式实在是没有什么可说的,所以笔记由原来计划的三篇缩减到了两篇,通过这两篇笔记呢,我知道这些笔记可能虽然没有什么人看,但是看的那几个人应该以及初步掌握了工厂模式的精髓了,并且能在之后的开发中能有所应用。

github下载: github.com/hanshuaikan…

最后,我是韩数,欢迎关注我,我们下篇笔记再见。