java三大工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)
1、概述
工厂模式主要是通过把创建对象的代码包装起来,做到创建对象的代码与具体的业务逻辑代码相隔离的目的。
工厂模式可以细分为:简单工厂模式,工厂方法模式,抽象工厂模式。
2、简单工厂模式
简单工厂的标准类图

首先,我们举个例子,我们需要生产3种不同的车类型(电车,油车,混能车),用户自行指定需要什么车,就给用户创建什么车的对象。
分析一下,电车,油车,混能车都是具体的类,他们应该同属于车这个抽象类,然后我们需要建一个工厂类来根据用户的指定,创建指定的车型类。所以再根据上面的图,我们就可以开始写代码模拟实现这个例子。
创建车的抽象接口
public interface Car {
public void createCar();
}
创建具体车型类,并实现Car接口
public class Ecar implements Car{
@Override
public void createCar() {
System.out.println("造出电车");
}
}
public class Ocar implements Car{
@Override
public void createCar() {
System.out.println("造出油车");
}
}
public class Mcar implements Car{
@Override
public void createCar() {
System.out.println("造出混能车");
}
}
创建工厂类
public class CarFactory {
public Car createCar(String s) {
Car car = null;
switch (s) {
case "电车":
car = new Ecar();
break;
case "油车":
car = new Ocar();
break;
case "混能车":
car = new Mcar();
break;
}
return car;
}
}
测试
public class Test1 {
public static void main(String[] args) {
CarFactory carFactory = new CarFactory();
Car car = carFactory.createCar("油车");
car.createCar();
}
}
造出油车
优点:
将对象的创建交给专门的工厂类负责,实现了对象的创建和对象的使用分离。
一个调用者想创建一个对象,只要知道其名称就可以了,灵活性高。
屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
增加新的具体产品需要修改工厂类的判断逻辑代码。违背开闭原则。
3、工厂方法模式
那么为了解决简单工厂的违反开闭原则,就出现了工厂方法模式,每一个具体车型类,有一个自己的创建自己对象的工厂,从而避免违法开闭原则。
网上找的工厂方法模式类图参考,结构都相似。

其他的类不变,我们先修改CarFactory类改为接口。
public interface CarFactory {
public Car createCar();
}
创建电车型类的工厂
public class EcarFactory implements CarFactory{
@Override
public Car createCar() {
return new Ecar();
}
}
其他的工厂同上,就不写了。
测试
public class Test1 {
public static void main(String[] args) {
CarFactory carFactory = new EcarFactory();
Car car = carFactory.createCar();
car.createCar();
}
}
造出电车
优点:
用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。不会修改原有的代码,不会违法开闭原则。
缺点:
新产品的创建,只需多写一个相应的工厂类和具体类,灵活度没有简单工厂模式高。
类的个数容易过多,增加复杂度。
抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
4、抽象工厂模式
通过上面工厂方法的缺点可以看到,简单工厂和工厂方法模式都是能生产一种产品,如果我需要创建比亚迪,宝马,奔驰品牌的电车,油车,混能车,上述的工厂模式很难实现,所有我们就可以用到抽象工厂模式。
抽象工厂模式类图

先创建电车,油车,混能车的抽象接口
这个car写错了写成了cat不过不影响效果
public interface Ecat {
public void createCat();
}
public interface Mcat {
public void createCat();
}
public interface Ocat {
public void createCat();
}
创建每个牌子车型的具体类
public class BenzEcat implements Ecat {
@Override
public void createCat() {
System.out.println("奔驰电车");
}
}
public class BmwEcat implements Ecat {
@Override
public void createCat() {
System.out.println("宝马电车");
}
}
public class BydEcat implements Ecat {
public void createCat(){
System.out.println("比亚迪电车");
}
}
其他两个车型就不写了,写法类似。
创建抽象汽车工厂接口
public interface CatFactory {
public Ecat createEcat();
public Ocat createOcat();
public Mcat createMcat();
}
创建具体品牌的工厂,实现车的接口工厂
public class BydCatFactory implements CatFactory{
@Override
public Ecat createEcat() {
return new BydEcat();
}
@Override
public Ocat createOcat() {
return new BydOcat();
}
@Override
public Mcat createMcat() {
return new BydMcat();
}
}
public class BmwCatFactory implements CatFactory{
@Override
public Ecat createEcat() {
return new BmwEcat();
}
@Override
public Ocat createOcat() {
return new BmwOcat();
}
@Override
public Mcat createMcat() {
return new BmwMcat();
}
}
public class BenzCatFactory implements CatFactory{
@Override
public Ecat createEcat() {
return new BenzEcat();
}
@Override
public Ocat createOcat() {
return new BenzOcat();
}
@Override
public Mcat createMcat() {
return new BenzMcat();
}
}
测试
public class test1 {
public static void main(String[] args) {
//抽象工厂测试
CatFactory catFactory = new BydCatFactory();
Ocat ocat = catFactory.createOcat();
ocat.createCat();
}
}
比亚迪油车
优点:
增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
缺点:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,灵活性低
5、抽象工厂模式改进为简单抽象工厂模式
只用再上述的工厂类,改为下列新的工厂类。
public class SimpleAbstractCatFactory {
public Ecat createEcat(String brand) {
Ecat ecat = null;
switch (brand) {
case "比亚迪":
ecat = new BydEcat();
break;
case "宝马":
ecat = new BmwEcat();
break;
case "奔驰":
ecat = new BenzEcat();
break;
}
return ecat;
}
public Ocat createOcat(String brand) {
Ocat ocat = null;
switch (brand) {
case "比亚迪":
ocat = new BydOcat();
break;
case "宝马":
ocat = new BmwOcat();
break;
case "奔驰":
ocat = new BenzOcat();
break;
}
return ocat;
}
public Mcat createMcat(String brand) {
Mcat mcat = null;
switch (brand) {
case "比亚迪":
mcat = new BydMcat();
break;
case "宝马":
mcat = new BmwMcat();
break;
case "奔驰":
mcat = new BenzMcat();
break;
}
return mcat;
}
}
测试
SimpleAbstractCatFactory simpleAbstractCatFactory = new SimpleAbstractCatFactory();
Ecat ecat = simpleAbstractCatFactory.createEcat("比亚迪");
ecat.createCat();
优点:灵活性高。
缺点:违反开闭原则。
6、总结
通过我们上面的各种例子,我们可以发现不管我们怎么修改设计方式,都不能够同时满足灵活性高和不违反开闭原则。如果要同时满足的话,就需要引入反射的思想,通过反射+抽象工厂的方式实现。
更多推荐
所有评论(0)