本文最后更新于:3 years ago
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于 创建型模式 ,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
如果想了解工厂模式的具体的介绍,菜鸟教程介绍得比较详细↓菜鸟教程-工厂模式
结构图
优缺点 优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点: 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
使用场景 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。
实现代码 简单工厂 首先实现需求,任意定制交通工具,然后实现Moveable()接口
这里我们首先创建三个对象,Car、Plane、Broom,实现Moveable接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Moveablepublic interface Moveable { void go () ; } Carpublic class Car implements Moveable { @Override public void go () { System.out.println("Car go" ); } } Planepublic class Plane implements Moveable { @Override public void go () { System.out.println("Plane go" ); } } Broompublic class Broom implements Moveable { @Override public void go () { System.out.println("Broom go" ); } }Mainpublic static void main (String[] args) { Moveable m = new Car(); m.go(); }
在任意定制交通工具之后,这时我要求任意定制生产过程 什么意思呢?比如说,当我们生产交通工具时,我们要求控制其权限 有人会说,我在new 之前写一串判断的代码,但仔细想想,我们不止单单Car一个类, 对于Car、Broom、Plane等等,它的权限是不一样的 这就意味着,如果你在new之前写了判断,则创建不同的类型实例,就要更改代码
解决方法 我们可以将产生对象的方法交给工厂去完成,并且此时可以在工厂中判断其权限,设置日志啥的。 接着创建简单工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 SimpleVehicleFactorypublic class SimpleVehicleFactory { public Car createCar () { return new Car(); } public Broom createBroom () { return new Broom(); } public Plane createPlane () { return new Plane(); } }
创建好工厂以后,我们只需要直接使用工厂即可
public static void main (String[] args) { SimpleVehicleFactory svf = new SimpleVehicleFactory(); svf.createCar(); }
这就是简单工厂,本质就是一个简单的多态。 但弊端还是要说的: 简单工厂的可扩展性不好 当新添加一种类时,又要在其中加入新的方法,并且 before processing 还是要写死。
工厂方法 此时对于以上情况,我们还可以针对每一种产品做一种工厂:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 CarFactorypublic class CarFactory { public Moveable create () { System.out.println("a car created!" ); return new Car(); } } BroomFactorypublic class BroomFactory { public Moveable create () { System.out.println("a broom created!" ); return new Broom(); } } PlaneFactorypublic class PlaneFactory { public Moveable create () { System.out.println("a plane created!" ); return new Plane(); } }
Mianpublic static void main (String[] args) { Moveable moveable = new CarFactory().create(); moveable.go(); }
这样一看是不是就好多了,这就是工厂方法。 为每一个子类建立一个对应的工厂子类,这些工厂子类实现同一个抽象工厂接口。这样,创建不同工厂(交通工具),只需要实现不同的工厂子类。当有新工厂(交通工具)加入时,新建具体工厂继承抽象工厂,而不用修改任何一个类。
抽象工厂 接着我们继续提出要求,要求定制产品一族。 什么意思呢? 上面我们制造了交通工具,接下来我们要求,一个司机开着汽车,吃着面包,吸着烟
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 Carpublic class Car { public void go () { System.out.println("DiDiDi..." ); } } Breadpublic class Bread { public void eat () { System.out.println("bread..." ); } } Smokingpublic class Smoking { public void act () { System.out.println("XiXiXi..." ); } } Mainpublic class Main { public static void main (String[] args) { Car car = new Car(); car.go(); Bread bread = new Bread(); bread.eat(); Smoking smoking = new Smoking(); smoking.act(); } }
这个时候,我们再提出将这个司机改为原始人。原始人骑着猪,吃着肉,喝着水。 难实现吗?一点也不难,但当我们在实现的时候,Main方法中的定义、调用都需要重写,极其麻烦。
这个时候,我们就需要用到抽象工厂的思想了。
大致思想是这样的,首先,我们创建一个抽象工厂,它会产生三种不同的抽象产品Act、Food、Vehicle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 AbstractFactorypublic abstract class AbstractFactory { abstract Food createFood () ; abstract Act createAct () ; abstract Vehicle createVehicle () ; } Actpublic abstract class Act { abstract void act () ; } Foodpublic abstract class Food { abstract void eat () ; } Vehiclepublic abstract class Vehicle { abstract void go () ; }
接着我们再将Car、Bread、Smoking继承Vehicle、Food、Act三个抽象方法。 此时是不是就很明确了。接着我们再创建一个实体类来实现原始人这一族
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 TestFactorypublic class TestFactory extends AbstractFactory { @Override Food createFood () { return new Meat(); } @Override Act createAct () { return new Drinking(); } @Override Vehicle createVehicle () { return new Pig(); } } Mainpublic class Main { public static void main (String[] args) { AbstractFactory af = new TestFactory(); Vehicle pig = af.createVehicle(); pig.go(); Food meat = af.createFood(); meat.eat(); Act drinking = af.createAct(); drinking.act(); } }
此时我们并不需要改动大量的代码,只需将AbstractFactory af = new TestFactory();
TestFactory()改为我们所需要用到的工厂即可。
工厂方法比较方便在于产品单一维度上的扩展,只需加新产品加工厂 而抽象工厂在产品族上扩展时,方便在于产品族的扩展,但是在产品单一维度上扩展时,你的抽象工厂需要加方法,具体工厂要加更多的方法
总结 简单工厂:唯一工厂类,一个产品抽象类,工厂类的创建方法依据入参判断并创建具体产品对象。 工厂方法:多个工厂类,一个产品抽象类,利用多态创建不同的产品对象,避免了大量的if-else判断。 抽象工厂:多个工厂类,多个产品抽象类,产品子类分组,同一个工厂实现类创建同组中的不同产品,减少了工厂子类的数量。
参考文章:简单工厂模式、工厂方法模式和抽象工厂模式有何区别?