简单工厂、工厂方法模式、抽象工厂模式

只为每天积累一点点。。。

简单工厂、工厂方法模式、抽象工厂模式的简单原理。

一、引子

话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰)、Bmw(宝马)、Audi(奥迪)),还雇了司机为他开车。不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上 Audi后他说“开奥迪车!”。
你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!
幸运的是这种有病的现象在OO语言中可以避免了。下面以Java语言为基础来引入我们本文的主题:工厂模式!

二、简介

工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:
1. 简单工厂模式(Simple Factory)
2. 工厂方法模式(Factory Method)
3. 抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。两者皆可,这本为使用《Java与模式》的分类方法。
在什么样的情况下我们应该记得使用工厂模式呢?大体有两点:
1.在编码时不能预见需要创建哪种类的实例。
2.系统不应依赖于产品类实例如何被创建、组合和表达的细节
工厂模式能给我们的OOD、OOP带来哪些好处呢??

三、简单工厂模式

这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改)。
它由三种角色组成:
工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,根据逻辑不同,产生具体的工厂产品。如例子中的Driver类。
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。如例中的Car接口。
具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现,如例子中的Benz、Bmw类。

来用类图来清晰的表示下的它们之间的关系:

下面就来给那个暴发户治病:在使用了简单工厂模式后,现在暴发户只需要坐在车里对司机说句:“开车”就可以了。来看看怎么用代码实现的:(为方便起见,所有的类放在一个文件中,故有一个类被声明为public)

  1. //抽象产品
  2. abstract class Car{
  3. private String name;
  4. public abstract void drive();
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. }
  12. //具体产品
  13. class Benz extends Car{
  14. public void drive(){
  15. System.out.println(this.getName()+"----go-----------------------");
  16. }
  17. }
  18. class Bmw extends Car{
  19. public void drive(){
  20. System.out.println(this.getName()+"----go-----------------------");
  21. }
  22. }
  23. //简单工厂
  24. class Driver{
  25. public static Car createCar(String car){
  26. Car c = null;
  27. if("Benz".equalsIgnoreCase(car))
  28. c = new Benz();
  29. else if("Bmw".equalsIgnoreCase(car))
  30. c = new Bmw();
  31. return c;
  32. }
  33. }
  34. //老板
  35. public class BossSimplyFactory {
  36. public static void main(String[] args) throws IOException {
  37. //老板告诉司机我今天坐奔驰
  38. Car car = Driver.createCar("benz");
  39. car.setName("benz");
  40. //司机开着奔驰出发
  41. car.drive();
  42. }
  43. <span style="font-family: courier new,courier;">}</span>

如果老板要坐奥迪,同理。

这便是简单工厂模式了。那么它带了了什么好处呢?
首先,符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品(正如暴发户所为)。

面我们从开闭原则上来分析下简单工厂模式。当暴发户增加了一辆车的时候,只要符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。(即创
建一个新的车类,继承抽象产品Car)那么
对于产品部分来说,它是符合开闭原则的——对扩展开放、对修改关闭;但是工厂类不太理想,因为每增加一辆车,都要在工厂类中增加相应的商业逻辑和判
断逻辑,这显自然是违背开闭原则的。

而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了。
正如我前面提到的简单工厂模式适用于业务简单的情况下或者具体产品很少增加的情况。而对于复杂的业务环境可能不太适应了。这就应该由工厂方法模式来出场了!!

四、工厂方法模式
抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
来用类图来清晰的表示下的它们之间的关系:

话说暴发户生意越做越大,自己的爱车也越来越多。这可苦了那位司机师傅了,什么车它都要记得,维护,都要经过他来使用!于是暴发户同情他说:我给你分配几个人手,你只管管好他们就行了!于是工厂方法模式的管理出现了。代码如下:

  1. //抽象产品
  2. abstract class Car{
  3. private String name;
  4. public abstract void drive();
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. }
  12. //具体产品
  13. class Benz extends Car{
  14. public void drive(){
  15. System.out.println(this.getName()+"----go-----------------------");
  16. }
  17. }
  18. class Bmw extends Car{
  19. public void drive(){
  20. System.out.println(this.getName()+"----go-----------------------");
  21. }
  22. }
  23. //抽象工厂
  24. abstract class Driver{
  25. public abstract Car createCar(String car) throws Exception;
  26. }
  27. //具体工厂(每个具体工厂负责一个具体产品)
  28. class BenzDriver extends Driver{
  29. public Car createCar(String car) throws Exception {
  30. return new Benz();
  31. }
  32. }
  33. class BmwDriver extends Driver{
  34. public Car createCar(String car) throws Exception {
  35. return new Bmw();
  36. }
  37. }
  38. //老板
  39. public class Boss{
  40. public static void main(String[] args) throws Exception {
  41. Driver d = new BenzDriver();
  42. Car c = d.createCar("benz");
  43. c.setName("benz");
  44. c.drive();
  45. }
  46. }

使用开闭原则来分析下工厂方法模式。当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,
那么就可以被客户使用,而不必去修改任何已有的代码。(即当有新产品时,只要创建并基础抽象产品;新建具体工厂继承抽象工厂;而不用修改任何一个类)工厂
方法模式是完全符合开闭原则的!

使用工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所
希望的。所以我建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用
简单工厂模式来实现。
当然特殊的情况,就要特殊对待了:对于系统中存在不同的产品树,而且产品树上存在产品族(下一节将解释这个名词)。那么这种情况下就可能可以使用抽象工厂模式了。

五、小结

让我们来看看简单工厂模式、工厂方法模式给我们的启迪:
如果不使用工厂模式来实现我们的例子,也许代码会减少很多——只需要实现已有的车,不使用多态。但是在可维护性上,可扩展性上是非常差的(你可以想象一下添加一辆车后要牵动的类)。因此为了提高扩展性和维护性,多写些代码是值得的。

六、抽象工厂模式

先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。

图中的BmwCar和BenzCar就是两个产品树(产品层次结构);而如图所示的BenzSportsCar和BmwSportsCar就
是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzBusinessCar也是一个产品族。
可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。
而且使用抽象工厂模式还要满足一下条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品以其使用。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

  1. //抽象产品(Bmw和Audi同理)
  2. abstract class BenzCar{
  3. private String name;
  4. public abstract void drive();
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. }
  12. //具体产品(Bmw和Audi同理)
  13. class BenzSportCar extends BenzCar{
  14. public void drive(){
  15. System.out.println(this.getName()+"----BenzSportCar-----------------------");
  16. }
  17. }
  18. class BenzBusinessCar extends BenzCar{
  19. public void drive(){
  20. System.out.println(this.getName()+"----BenzBusinessCar-----------------------");
  21. }
  22. }
  23. abstract class BmwCar{
  24. private String name;
  25. public abstract void drive();
  26. public String getName() {
  27. return name;
  28. }
  29. public void setName(String name) {
  30. this.name = name;
  31. }
  32. }
  33. class BmwSportCar extends BmwCar{
  34. public void drive(){
  35. System.out.println(this.getName()+"----BmwSportCar-----------------------");
  36. }
  37. }
  38. class BmwBusinessCar extends BmwCar{
  39. public void drive(){
  40. System.out.println(this.getName()+"----BmwBusinessCar-----------------------");
  41. }
  42. }
  43. abstract class AudiCar{
  44. private String name;
  45. public abstract void drive();
  46. public String getName() {
  47. return name;
  48. }
  49. public void setName(String name) {
  50. this.name = name;
  51. }
  52. }
  53. class AudiSportCar extends AudiCar{
  54. public void drive(){
  55. System.out.println(this.getName()+"----AudiSportCar-----------------------");
  56. }
  57. }
  58. class AudiBusinessCar extends AudiCar{
  59. public void drive(){
  60. System.out.println(this.getName()+"----AudiBusinessCar-----------------------");
  61. }
  62. }
  63. //抽象工厂
  64. abstract class Driver3{
  65. public abstract BenzCar createBenzCar(String car) throws Exception;
  66. public abstract BmwCar createBmwCar(String car) throws Exception;
  67. public abstract AudiCar createAudiCar(String car) throws Exception;
  68. }
  69. //具体工厂
  70. class SportDriver extends Driver3{
  71. public BenzCar createBenzCar(String car) throws Exception {
  72. return new BenzSportCar();
  73. }
  74. public BmwCar createBmwCar(String car) throws Exception {
  75. return new BmwSportCar();
  76. }
  77. public AudiCar createAudiCar(String car) throws Exception {
  78. return new AudiSportCar();
  79. }
  80. }
  81. class BusinessDriver extends Driver3{
  82. public BenzCar createBenzCar(String car) throws Exception {
  83. return new BenzBusinessCar();
  84. }
  85. public BmwCar createBmwCar(String car) throws Exception {
  86. return new BmwBusinessCar();
  87. }
  88. public AudiCar createAudiCar(String car) throws Exception {
  89. return new AudiBusinessCar();
  90. }
  91. }
  92. //老板
  93. public class BossAbstractFactory {
  94. public static void main(String[] args) throws Exception {
  95. Driver3 d = new BusinessDriver();
  96. AudiCar car = d.createAudiCar("");
  97. car.drive();
  98. }
  99. }

其中:BenzSportCar和BenzBusinessCar属于产品树;同理BmwSportCar和BmwBusinessCar。而BenzSportCar和BmwSportCar和AudiSportCar属于产品族。

所以抽象工厂模式一般用于具有产品树和产品族的场景下。

抽象工厂模式的缺点:如果需要增加新的产品树,那么就要新增三个产品类,比如VolvoCar,VolvoSportCar,VolvoSportCar,并且要修改三个工厂类。这样大批量的改动是很丑陋的做法。

所以可以用简单工厂配合反射来改进抽象工厂:
UML图略。

  1. abstract class BenzCar{
  2. private String name;
  3. public abstract void drive();
  4. public String getName() {
  5. return name;
  6. }
  7. public void setName(String name) {
  8. this.name = name;
  9. }
  10. }
  11. class BenzSportCar extends BenzCar{
  12. public void drive(){
  13. System.out.println(this.getName()+"----BenzSportCar-----------------------");
  14. }
  15. }
  16. class BenzBusinessCar extends BenzCar{
  17. public void drive(){
  18. System.out.println(this.getName()+"----BenzBusinessCar-----------------------");
  19. }
  20. }
  21. abstract class BmwCar{
  22. private String name;
  23. public abstract void drive();
  24. public String getName() {
  25. return name;
  26. }
  27. public void setName(String name) {
  28. this.name = name;
  29. }
  30. }
  31. class BmwSportCar extends BmwCar{
  32. public void drive(){
  33. System.out.println(this.getName()+"----BmwSportCar-----------------------");
  34. }
  35. }
  36. class BmwBusinessCar extends BmwCar{
  37. public void drive(){
  38. System.out.println(this.getName()+"----BmwBusinessCar-----------------------");
  39. }
  40. }
  41. abstract class AudiCar{
  42. private String name;
  43. public abstract void drive();
  44. public String getName() {
  45. return name;
  46. }
  47. public void setName(String name) {
  48. this.name = name;
  49. }
  50. }
  51. class AudiSportCar extends AudiCar{
  52. public void drive(){
  53. System.out.println(this.getName()+"----AudiSportCar-----------------------");
  54. }
  55. }
  56. class AudiBusinessCar extends AudiCar{
  57. public void drive(){
  58. System.out.println(this.getName()+"----AudiBusinessCar-----------------------");
  59. }
  60. }
  61. /**
  62. * 简单工厂通过反射改进抽象工厂及其子工厂
  63. * @author Administrator
  64. *
  65. */
  66. class Driver3{
  67. public static BenzCar createBenzCar(String car) throws Exception {
  68. return (BenzCar) Class.forName(car).newInstance();
  69. }
  70. public static BmwCar createBmwCar(String car) throws Exception {
  71. return (BmwCar) Class.forName(car).newInstance();
  72. }
  73. public static AudiCar createAudiCar(String car) throws Exception {
  74. return (AudiCar) Class.forName(car).newInstance();
  75. }
  76. }
  77. //客户端
  78. public class SimpleAndAbstractFactory {
  79. public static void main(String[] args) throws Exception {
  80. AudiCar car = Driver3.createAudiCar("com.java.pattendesign.factory.AudiSportCar");
  81. car.drive();
  82. }
  83. }
时间: 2024-10-08 12:04:40

简单工厂、工厂方法模式、抽象工厂模式的相关文章

简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

结合简单示例和UML图,讲解工厂模式简单原理. 一.引子 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说"开奔驰车!",坐上Bmw后他说"开宝马车!",坐上 Audi后他说"开奥迪车!".你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!幸运的是这种有

大话设计模式之简单工厂模式&amp;工厂方法模式&amp;抽象工厂模式

创造类模式分为三种:简单工厂模式,工厂模式和抽象工厂模式. 定义: 简单工厂模式:用一个单独的类来做创造实例的过程. 工厂模式:一个用于创建对象的接口,让子类决定实例化哪一个类,讲一个类的实例化 延迟到其子类. 抽象工厂模式:为创建一组相关或相互依赖的对象的类,而不指定具体类. 结构图: 这是简单工厂的结构图,从图中就很好理解. 简单工厂的优点: 根据用户需要,new出需要的对象. 但是简单工厂弊端: 当新加入一个功能是,就要修改工厂.这个时候,就需要工厂模式了. 从图中我们可以看出: 工厂模式

Java工厂模式(简单工厂、工厂方法、抽象工厂)

工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory Method).3:抽象工厂(Abstract Factory). 简单工厂(Simple Factory)又叫静态工厂,是工厂模式三中状态中结构最为简单的.主要有一个静态方法,用来接受参数,并根据参数来决定返回实现同一接口的不同类的实例.我们来看一个具体的例子:假设一家工厂,几生产洗衣机,有生产冰箱

结合实例分析简单工厂模式&amp;工厂方法模式&amp;抽象工厂模式的区别

之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略.这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个设计模式,但很多地方都用到了工厂模式,(如解析xml中,jdbc连接数据库等)利用好工厂模式对程序的设计很有用处.工厂模式在一些设计模式的书中分为简单工厂模式,工厂方法模式和抽象工厂模式三类.也有把工厂方法模式划分到抽象工厂模式的,认为工厂方法是抽象工厂模式的特例的一种,就是只有一个要实现的产品接口

简单工厂和工厂方法以及抽象工厂模式

工厂模式:定义一个用于创建对象的借口,让子类决定实例化哪一个类 抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 个人觉得这个区别在于产品,如果产品单一,最合适用工厂模式,但是如果有多个业务品种.业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方 式.再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的. 再来看看工厂方法模式与抽象工厂模式对比: 工厂方法模式 抽象工厂模式 针对的是一个产品等级结构 针对的

对比总结三个工厂模式(简单工厂,工厂方法,抽象工厂)

前言 简单工厂模式,工厂方法模式,抽象工厂模式,这三个模式,当然还有单例模式,建造者模式等等,应该是日常工作中常用的,尤其是工厂模式,应该是最最常见的模式,对理解面向对象有重要的实际意义. 简单工厂模式 最简单,最直接,能满足大部分日常需求,不足是工厂类太简单——无法满足开闭原则,对多个产品的扩展不利 工厂方法模式——交给子类去创建 工厂方法模式,有了进步,把工厂类进行改进,提升为一个抽象类(接口),把对具体产品的实现交给对应的具体的子类去做,解耦多个产品之间的业务逻辑. 前面都是针对一个产品族

设计模式(Python)-简单工厂,工厂方法和抽象工厂模式

本系列文章是希望将软件项目中最常见的设计模式用通俗易懂的语言来讲解清楚,并通过Python来实现,每个设计模式都是围绕如下三个问题: 为什么?即为什么要使用这个设计模式,在使用这个模式之前存在什么样的问题? 是什么?通过Python语言来去实现这个设计模式,用于解决为什么中提到的问题. 怎么用?理解了为什么我们也就基本了解了什么情况下使用这个模式,不过在这里还是会细化使用场景,阐述模式的局限和优缺点. 这次的主角是简单工厂,工厂方法和抽象工厂模式,由于这几个模式联系紧密,有一定的相似性,所以放在

简单工厂模式&amp;工厂方法模式&amp;抽象工厂模式的区别

之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略.这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个设计模式,但很多地方都用到了工厂模式,(如解析xml中,jdbc连接数据库等)利用好工厂模式对程序的设计很有用处.工厂模式在一些设计模式的书中分为简单工厂模式,工厂方法模式和抽象工厂模式三类.也有把工厂方法模式划分到抽象工厂模式的,认为工厂方法是抽象工厂模式的特例的一种,就是只有一个要实现的产品接口

Java设计模式—工厂方法模式&amp;抽象工厂模式

工厂方法模式与抽象工厂模式都是设计模式中重要而且常见的模式.       工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 通用类图如下: 在工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义:Creator为抽象创建 类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的. 工厂方法模式的扩展方式有很多种,下边是工厂方法模式一个比较实用的源代码: 抽象产品类: pub

工厂模式—工厂方法与抽象工厂的战争

概述 什么是工厂方法?什么是抽象工厂? 工厂方法是指工厂生产产品,而抽象工厂是生产产品系列.例如,工厂方法是只生产运输工具比如马车.公共汽车.自行车,而抽象工厂生产轮胎.螺丝钉交通工具零件. 工厂方法模式定义了一个创建对象的接口,但由子类决定实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类. 简单工厂 交通工具创建者类 public interface VehicleFactory { Vehicle creat