前言
在23中设计模式中,工厂方法属于创建型的设计模式,只有工厂方法和抽象工厂两种,但是实际我们常与简单工厂混淆,因为简单工厂模式违背了开闭原则。
什么是开闭原则:开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
所以简单工厂不属于设计模式内的,但是并不是说简单工厂是错误的,只是根据具体情况使用而已。
下面我就针对简单工厂、工厂方法、抽象工厂结合Demo演示给大家。
正文
如图,就是工厂模式的划分。
简单工厂
概念:一个工厂类根据传入的参量决定创建出那一种产品类的实例。
想象一下汽车生产厂生产汽车,有两个工厂,分别是宝马和奔驰,客户想要买这两种车,就要分别去这两个工厂去买,结合在代码里就是客户分别传递不同的参数才可以得到不同的对象。
首先我们需要一个接口,用来返回不同的品牌的汽车。
代码语言:javascript复制public interface Car {
void produce();
}
然后我们需要两个汽车
代码语言:javascript复制public class Benz implements Car {
public void produce() {
System.out.println("生产一辆奔驰");
}
}
代码语言:javascript复制public class BMW implements Car {
public void produce() {
System.out.println("生产一辆宝马");
}
}
接下来就是工厂,这个工厂就是根据客户传过来的不同参数返回不同的汽车。
代码语言:javascript复制public class CarFactory {
public Car produce(String type) {
if ("bmw".equals(type)) {
return new BMW();
} else if ("benz".equals(type)) {
return new Benz();
} else {
System.out.println("类型错误");
}
return null;
}
}
最后来了一个顾客说是要买宝马,让我们来测试一下吧
代码语言:javascript复制public class SimpleFactoryTest {
public static void main(String[] args) {
CarFactory factory = new CarFactory();
Car car = factory.produce("bmw");
car.produce();
}
}
大家看代码可以得知,现在是两个车,就要写两个if去判断,如果以后出现很多个产品那么就就要在工厂方法里写多个if ,这样就会造成拓展业务需要修改原有代码来实现,这样的写法可以实现,但是很low,建议同学们尝试以下两种。
工厂方法模式
概念:定义一个创建对象的接口,让子类决定实例化那个类。
工厂模式细分的话有两种,我在代码里会讲解一种,另一种在示例代码中体现,被我注释掉的就是普通工厂方法,大家一看便知。
与简单工厂重复的代码我就贴在一个代码块中了。
代码语言:javascript复制public interface Car {
void produce();
}
public class Benz implements Car {
public void produce() {
System.out.println("生产一辆奔驰");
}
}
public class BMW implements Car {
public void produce() {
System.out.println("生产一辆宝马");
}
}
不同的地方就是工厂的写法,我们一个汽车品牌就新建一个工厂方法。
代码语言:javascript复制public class BenzCarFactory {
/**
* 工厂方法
* @return
*/
// public Car produceBenz() {
// return new Benz();
// }
/**
* 静态工厂方法
*
* @return
*/
public static Car produceBenz() {
return new Benz();
}
}
代码语言:javascript复制public class BMWCarFactory {
/**
* 工厂方法
* @return
*/
// public Car produceBMW() {
// return new BMW();
// }
/**
* 静态工厂方法
*
* @return
*/
public static Car produceBMW() {
return new BMW();
}
}
因为只静态的方法,那么在jvm加载时就已经创建了,所以我们在引用的时候就不用new工厂对象了,这也是普通工厂方法与静态工厂方法的区别所在。
让我们看一下客户是怎么购买汽车的。
代码语言:javascript复制public class FactoryMethodTest {
//psvm
public static void main(String[] args) {
/**
* 工厂方法
*/
// BenzCarFactory factory = new BenzCarFactory();
// Car car = factory.produceBenz();
// car.produce();
/**
* 静态工厂方法
*/
Car car = BenzCarFactory.produceBenz();
car.produce();
}
}
可以看出,每个工厂只生产一种产品,客户端通过不同的工厂去生产不同的产品。这样做的好处就是我们对业务进行拓展时不用更改代码,只需要新增一个拓展对产品或者对象就可以,这也是最简单也是我认为最常用对工厂方法了。
抽象工厂
概念:创建相关或依赖对象的家族,而无需明确指定具体类。
抽象工厂适用于复杂业务需求,复杂的产品生产场景中。怎么复杂呢?就是产品属性多了一个纬度,之前我们都是生产汽车,但是现在要区分出生产的颜色,对汽车的要求不仅仅是品牌还有颜色了。
来看看具体的代码实现:
首先定义三种颜色的接口
代码语言:javascript复制public interface Black {
void create();
}
public interface Red {
void create();
}
public interface White {
void create();
}
然后定义我们存在的产品,我们现在只有黑色奔驰,黑色宝马,白色奔驰,白色宝马,红色奥迪。分别创建这五个产品的类。
代码语言:javascript复制public class BenzBlack implements Black {
public void create() {
System.out.println("黑色奔驰");
}
}
public class BenzWhite implements White {
public void create() {
System.out.println("白色奔驰");
}
}
public class BMWBlack implements Black {
public void create() {
System.out.println("黑色宝马");
}
}
public class BMWWhite implements White {
public void create() {
System.out.println("白色宝马");
}
}
public class RedAudi implements Red {
public void create() {
System.out.println("红色奥迪");
}
}
然后我们定义工厂接口,工厂接口是把刚才颜色接口进行了统一整理在一起。说明我们现在可以生产这三种颜色任意品牌汽车。
所以说对业务拓展性非常高。
代码语言:javascript复制public interface CarFactory {
Black black();
White white();
Red red();
}
那么就让我们随意创建三种汽车的工厂。
代码语言:javascript复制public class AudiFactory implements CarFactory{
public Black black() {
return null;
}
public White white() {
return null;
}
public Red red() {
return new RedAudi();
}
}
public class BenzFactory implements CarFactory {
public Black black() {
return new BenzBlack();
}
public White white() {
return new BenzWhite();
}
public Red red() {
return null;
}
}
public class BMWFactory implements CarFactory {
public Black black() {
return new BMWBlack();
}
public White white() {
return new BMWWhite();
}
public Red red() {
return null;
}
}
让我们来测试一下
代码语言:javascript复制public class AbstractFactoryMethodTest {
public static void main(String[] args) {
AudiFactory audi = new AudiFactory();
Red redAudi = audi.red();
redAudi.create();
BenzFactory benz = new BenzFactory();
Black blackBenz = benz.black();
blackBenz.create();
}
}
输出结果如下
如果要对以上代码有疑问,或者想要代码,可以加我微信 15524579896
总结
简单工厂模式适用于工厂类需要创建的对象比较少的情况,客户只需要传入具体的参数,就可以忽略工厂的生产细节,去获取想要的对象;
工厂方法模式,主要是针对单一产品结构的情景,拓展时只需增加一个工厂类就可以;
抽象工厂模式则是针对多级产品结构(系列产品)的一种工厂模式,拓展时增加多个类,改动比较大;
最后在说一下,每种模式都有自己的优点和弊端,没有最好的模式,只有最适合的模式,只要符合实际开发需求就是最好的。