Java设计模式之工厂模式分析【简单工厂、工厂方法、抽象工厂】

时间:2022-11-09 13:18:20

本文实例讲述了java设计模式之工厂模式。分享给大家供大家参考,具体如下:

一、 简单工厂

先来思考一个问题。我们平时写程序时,会有这种情况,a对象里面需要调用b对象的方法,这时我们使用的一般是new关键字来创建一个b实例,然后调用b实例的方法。这种做法的坏处在于:a类的方法实现直接调用了b类的类名(这种方式也被称为硬编码耦合),一旦系统需要重构:需要使用c类来代替b类时,程序就不得不修改a类代码,如果应用中有100个或者10000个类以硬编码方式耦合了b类,则需要修改100个、10000个地方,这显然是一种非常可怕的事情。

换一个角度来看这个问题:对已a对象而言,它只需要调用b对象的方法,并不关心b对象的实现、创建过程,考虑让b类实现一个ib接口,而a类只需要与ib接口耦合——a类并不直接使用new关键字来创建b实例,而是重新定义一个工厂类:ibfactory,由该工厂类负责创建ib实例,而a类用过调用ibfactory工厂的方法来得到ib的实例。通过以上设计:需要使用c类代替b类,则只需要让c类也实现ib接口,并改写ibfactory工厂中创建ib实例的实现代码,让该工厂产生c实例即可。这种将多个类对象交给工厂类来生成的设计方式叫做简单工厂模式。

以下是简单工厂模式的代码:

?
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
 * 简单工厂模式
 *
 * 需要工厂生产的对象实例所实现的共同的接口
 * 发型接口
 * @author administrator
 *
 */
public interface hair {
  /**
   * 画发型
   */
  public void draw();
}
/**
 * 左偏分发型
 * @author administrator
 *
 */
public class lefthair implements hair {
  @override
  public void draw() {
    system.out.println("----------------画左偏分发型-----------------");
  }
}
/**
 * 右偏分发型
 * @author administrator
 *
 */
public class righthair implements hair {
  @override
  public void draw() {
    system.out.println("-----------------画右偏分发型------------------");
  }
}
/**
 * 生产发型的工厂
 * 要生产什么发型 只需在这里改就行了
 * @author administrator
 *
 */
public class hairfactory {
  public hair gethair() {
    return new lefthair();
    //return new righthair();
  }
}
/**
 * 客户端测试类
 * @author administrator
 *
 */
public class hairtest {
  public static void main(string[] args) {
    hairfactory factory = new hairfactory();
    hair hair = factory.gethair();
    hair.draw();
  }
}

可以看到,如果想把hairtest里面生成的lefthair改成righthair,只需修改hairfactory里面gethair方法的实现即可。

使用简单工厂模式的优势在于:让对象的调用者和对象的创建过程分离,当对象调用者需要对象时,直接向工厂请求即可,从而避免了对象的调用者与对象实现类以硬编码方式耦合,以提高系统的可维护性、可扩展性。当然,工厂模式也有一个小小的缺陷,当产品修改时,工厂类也要做相应的修改,此处可使用策略模式进行解决,下面是代码。

?
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
35
36
37
38
39
40
public interface hairbuilder {
  /**
   * 制造发型
   * @return
   */
  public hair gethair();
}
public class lefthairbuilder implements hairbuilder {
  @override
  public hair gethair() {
    return new lefthair();
  }
}
public class righthairbuilder implements hairbuilder {
  @override
  public hair gethair() {
    return new righthair();
  }
}
public class hairfactory {
  private hairbuilder hairbuilder;
  public hairfactory(hairbuilder hairbuilder) {
    this.hairbuilder = hairbuilder;
  }
  public void sethairbuilder(hairbuilder hairbuilder) {
    this.hairbuilder = hairbuilder;
  }
  public hair gethair() {
    return hairbuilder.gethair();
  }
}
public class hairtest {
  public static void main(string[] args) {
//   hairbuilder builder = new lefthairbuilder();
    hairbuilder builder = new righthairbuilder();
    hairfactory factory = new hairfactory(builder);
    hair hair = factory.gethair();
    hair.draw();
  }
}

这种做法的好处是无需再去修改工厂类,将工厂里面的创建对量逻辑根据不同的策略抽象出来,程序需要创建什么对象,只需网工厂中传入相应的builder即可。

二、工厂方法

在简单工厂模式中,系统使用工厂类生产所有产品实例,且该工厂类决定生产哪个类的实例,即工厂类负责所有的逻辑判断、实例创建等工作。

如果不想再工厂类中进行逻辑判断,程序可以为不同的产品类提供不同的工厂,不同的工厂类生产不同的产品,无需再工厂类中进行复杂的逻辑判断。这就有点类似于上面的简单工厂模式结合策略模式,不同的是前者只有一个工厂,后者需要有多个工厂。下面是工厂方法模式的代码。

?
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
 * 工厂方法模式
 * 需要工厂生产的对象实例所实现的共同的接口
 * @author administrator
 *
 */
public interface person {
  public void drawperson();
}
public class man implements person {
  @override
  public void drawperson() {
    system.out.println("---------------------draw a man--------------------");
  }
}
public class women implements person {
  @override
  public void drawperson() {
    system.out.println("--------------------draw a women---------------------");
  }
}
/**
 * 生产人的工厂
 * @author administrator
 *
 */
public interface personfactory {
  //生产人
  public person getperson();
}
/**
 * 生产man的工厂
 * @author administrator
 *
 */
public class manfactory implements personfactory {
  @override
  public person getperson() {
    return new man();
  }
}
/**
 * 声场women的工厂
 * @author administrator
 *
 */
public class womenfactory implements personfactory {
  @override
  public person getperson() {
    return new women();
  }
}
/**
 * 客户端测试类
 * @author administrator
 *
 */
public class persontest {
  public static void main(string[] args) {
//   personfactory factory = new manfactory();
    personfactory factory = new womenfactory();
    person person = factory.getperson();
    person.drawperson();
  }
}

这种的典型的特点就是在客户端代码中根据不同的工厂生产其对应的产品,不必把复杂的逻辑都放在工厂类里面判断。这种实现有一个很明显的缺陷,就是客户端与工厂类进行了耦合。

三、抽象工厂

采用上面的工厂方法的设计架构,客户端代码成功与被调用对象的实现类分离,但带来了另一种耦合:客户端代码与不同的工厂类耦合。为了解决这种耦合的问题,考虑在增加一个工厂类,用来生成工厂实例,实现生产产品的工厂与客户端分离,这种设计方式被称为抽象工厂模式。下面是抽象工厂模式的代码

?
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
/**
 * 抽象工厂模式
 * 生产personfactory的工厂
 * @author administrator
 *
 */
public class personfactoryfactory {
  public static personfactory getpersonfactory(string type) {
    if(type.equalsignorecase("man")) {
      return new manfactory();
    } else {
      return new womenfactory();
    }
  }
}
/**
 * 客户端测试类
 * @author administrator
 *
 */
public class persontest {
  public static void main(string[] args) {
    personfactory factory = personfactoryfactory.getpersonfactory("man");
    person person = factory.getperson();
    person.drawperson();
  }
}

希望本文所述对大家java程序设计有所帮助。

原文链接:https://blog.csdn.net/zw19910924/article/details/52373892