工厂模式

网友投稿 517 2022-05-30

针对接口编程,可以隔离掉以后系统可能发生的一大堆改变。如果一个类中使用大量new出来的具体类,那么就等于是自找麻烦,因为一旦加入新的具体类,就必须修改代码。

我们可以将new的工作,交给一个对象去做,这个对象被我们称为“工厂”。

工厂(factory)处理创建对象的细节。把创建工作交给一个对象来处理的好处就是日后要修改时,只需要修改这个类即可。

我们很喜欢利用静态方法定义一个工厂,通常称为“静态工厂”,这样就不用使用创建对象的方法来实例化对象了,但这样的静态工厂有个缺点,就是不能通过继承来改变创建方法的行为。

简单工厂

其实,它不是一个设计模式,更像是一种编程习惯。下面的例子是关于简单工厂的:

UML:

没有使用工厂模前,FourSStore类的内部是这样的:

public class FourSStore { public Vehicle orderVehicle(String type){ Vehicle vehicle; switch (type) { case "car.Benz": vehicle = new Benz(); break; case "car.BMW": vehicle = new BMW(); break; case "car.BYD": vehicle = new BYD(); break; case "car.Volkswagon": vehicle = new Volkswagon(); break; } if(factory != null){ vehicle = factory.createVehicle(type); System.out.println(vehicle.brand()+"\n"); System.out.println(vehicle.price()+"\n"); System.out.println(vehicle.oilWear()+"\n"); System.out.println(vehicle.outputVolumn()+"\n"); return vehicle; } return null; } }

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

用了简单工厂模式后是这样的:

public class FourSStore { private SimpleVehicleFactory factory; public FourSStore(SimpleVehicleFactory factory){ this.factory = factory; } public Vehicle orderVehicle(String type){ Vehicle vehicle; if(factory != null){ vehicle = factory.createVehicle(type); System.out.println(vehicle.brand()+"\n"); System.out.println(vehicle.price()+"\n"); System.out.println(vehicle.oilWear()+"\n"); System.out.println(vehicle.outputVolumn()+"\n"); return vehicle; } return null; } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

就是把实化对象的工作,交给了工厂类simpleVehicleFactory类来完成,日后修改也会少很多,增加新的对象只需要在工厂中修改即可。

public class SimpleVehicleFactory { public Vehicle createVehicle(String type) { switch (type) { case "car.Benz": return new Benz(); case "car.BMW": return new BMW(); case "car.BYD": return new BYD(); case "car.Volkswagon": return new Volkswagon(); } return null; } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

简单工厂模式的代码已分享在GitHub上。

静态工厂

创建对象的方法是静态的,如:

public static Vehicle createVehicle(String type) { switch (type) { case "Benz": return new Benz(); case "BMW": return new BMW(); case "BYD": return new BYD(); case "Volkswagon": return new Volkswagon(); } return null; }

1

2

3

4

5

6

7

8

9

10

11

12

13

使用的时候就不用实例化工厂对象了,如:

Vehicle vehicle = StaticVehicleFactory.createVehicle(type);

1

2

静态工厂缺点就是不能通过继承来改变创建方法的行为。

静态工厂的demo也已分享在GitHub上了,欢迎下载。

工厂方法模式

**定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实化推迟到了子类。**如下有一个例子:

父类中有一个决定创建对象实例的抽象方法。

public abstract class FourSStore { public Vehicle orderVehicle(String type){ Vehicle vehicle = createVehicle(type); if(vehicle != null){ System.out.println(vehicle.brand()+"\n"); System.out.println(vehicle.price()+"\n"); System.out.println(vehicle.oilWear()+"\n"); System.out.println(vehicle.outputVolumn()+"\n"); return vehicle; } return null; } public abstract Vehicle createVehicle(String type); //决定创建对象实例的抽象方法,将由子类来实现 }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

子类:

public class GuangZhou4sStore extends FourSStore { @Override public Vehicle createVehicle(String type) { switch (type) { case "Benz": return new Benz(); case "BMW": return new BMW(); case "BYD": return new BYD(); case "Volkswagon": return new Volkswagon(); } return null; } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

测试:

public class Main { public static void main(String[] args) { FourSStore store = new GuangZhou4sStore(); store.orderVehicle("Volkswagon"); } }

1

2

3

4

5

6

7

8

9

10

测试结果

/home/wong/Desktop/FactoryMethodPattern/out/production/FactoryMethodPattern Main

Woldswagon

40000.0

1.3

12.0

Process finished with exit code 0

工厂方法模式与简单工厂模式,相同点就是都是创建创建对象实例的工作交给一个类来完成,不同点是工厂方法是交给子类从父类继承而来的抽象方法中来完成的,简单工厂模式则是自建的工厂类。

工厂方法模式帮助我们将产品的“实现”从“使用”中解耦。

上面的实例,都通过传参来决定要创建哪个产品,这叫做“参数化工厂方法”。如果是只生产一种对象(产品),那么可以不需要参数化。

抽象工厂模式

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产生的具体产品是什么。这样客户就可从具体的产品中解耦。

抽象工厂的每个方法实际上看起来都像是工厂方法。每个方法都被声明成抽象,而子类的方法覆盖这些方法来创建某些对象。

抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。

利用工厂方法创建对象,需要扩展一个类,并覆盖它的工厂方法。工厂方法是通过子类来创建对象。用这种做法,客户只需要知道他们所使用的抽象类型就可以了,而由子类来负责决定具体类型。

抽象工厂的具体工厂经常实现工厂方法来创建他们的产品。

抽象工厂提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品产生的方法。要想使用这个工厂必须先实例化它,然后将它传入一些针对抽象类型所写的代码中。

抽象工厂模式,如果要加入新产品就必须改变接口,即要修改抽象工厂中的抽象方法,子类也要提供实现,这个可能是抽象工厂模式的缺点之一。

工厂方法可以把客户代码从需要实例化的具体类中解耦。只要继承含有工厂方法的抽象对象,并实现其工厂方法就可以了。

抽像工厂模式的demo代码放在GitHub上了,欢迎下载学习。

其他

简单工厂把全部事情,在一个地方都处理完了。然而工厂方法却是创建了一个框架,让子类来决定要如何实现。简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法所拥有的弹性,因为简单工厂不能变更正在创建的产品。

将创建对象的代码集中在一个对象或方法中,可以避免代码中的重复,并且更方便以后的维护。这也意味着客户在实例化对象时,只会依赖于接口,而不是具体的类。

**当你直接实例化一个对象时,就是在依赖它的具体类。**在代码里减少对于具体类的依赖是件“好事”。**要依赖抽象,不要依赖具体类,这叫依赖倒置原则。**依赖倒置原则必須有以下三个特点:

变量不可以持有具体类的引用。如果用new就会持有具体类的引用,解决方法可以通过工厂来避免。

不要让类派生自具体类。可以派生自一个抽象(抽象类或接口)。

不要覆盖基类中已实现的方法。覆盖了基类已实现的方法,那么这个基类就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有子类所共享。

总结:

所有的工厂都是用来封装对象的创建。

简单工厂,虽然不是真正的设计模式,却不失为一个简单的方法,可以将客户程序从具体类解耦。

工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象

抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。

所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。

工厂方法允许将实例化延迟到子类进行。

抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。

依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象。

工厂帮助我们针对抽象编程,而不是针对具体类编程。

谢谢阅读!

GitHub

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:浅谈NB-IoT行业发展
下一篇:多云时代:云网融合的多云网络
相关文章