工厂模式内容补充理解

SYuan03 Lv4

简单工厂模式的扩展

Q

  1. 简单工厂模式的简化:在有些情况下工厂类可以由抽象产品角色扮演,一个抽象产品类同时也是子类的工厂,也就是说把静态工厂方法写到抽象产品类中。
  2. 有些情况下,产品本身只提供一两个方法,此时抽象产品可以和简单工厂进行角色合并。啥意思?举个例子,没理解

这两段话描述的是简单工厂模式的一种变体,也就是说在一些特定的情况下,简单工厂模式的结构可以进一步简化。具体来说,就是将工厂方法放入抽象产品类中,让抽象产品类既扮演产品角色,也扮演工厂角色。这种做法通常适用于产品类结构简单,功能相对单一的场景。下面通过一个例子来解释这个概念。

A

示例:图形绘制

假设我们有一个绘图应用,需要绘制不同类型的图形,如圆形、正方形等。每种图形都有自己特定的绘制方法。这里,图形(Shape)是一个抽象概念,具体的圆形(Circle)和正方形(Square)是具体的实现。

不使用简化的简单工厂模式

首先看传统的简单工厂模式实现:

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
// 抽象产品类
abstract class Shape {
abstract void draw();
}

// 具体产品类:圆形
class Circle extends Shape {
void draw() {
System.out.println("Drawing a circle");
}
}

// 具体产品类:正方形
class Square extends Shape {
void draw() {
System.out.println("Drawing a square");
}
}

// 简单工厂类
class ShapeFactory {
static Shape getShape(String type) {
if (type == null) {
return null;
}
if (type.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (type.equalsIgnoreCase("SQUARE")) {
return new Square();
}
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
// 抽象产品类同时扮演工厂角色
abstract class Shape {
abstract void draw();

// 静态工厂方法
static Shape getShape(String type) {
if (type == null) {
return null;
}
if (type.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (type.equalsIgnoreCase("SQUARE")) {
return new Square();
}
return null;
}
}

// 具体产品类:圆形
class Circle extends Shape {
void draw() {
System.out.println("Drawing a circle");
}
}

// 具体产品类:正方形
class Square extends Shape {
void draw() {
System.out.println("Drawing a square");
}
}

在这个简化后的模式中,Shape 类既定义了产品的接口(draw 方法),也提供了一个静态的工厂方法(getShape 方法)来根据类型创建具体的产品实例。这种做法简化了结构,减少了类的数量,特别适合那些产品类比较简单、数量不多的场景。这样,客户端只需要与Shape类交互即可获取具体的图形实例并调用其绘制方法,无需直接与具体的图形类或单独的工厂类交互,从而简化了客户端的使用复杂度。

Q

我有两个问题,那Square也会有getShape这个方法吗?那不是乱了吗?另外实体类可以调用静态方法吗?Shape是抽象类可以被实例化吗?

A

你提出的问题非常好,让我们逐一解答:

  1. Square类会有getShape这个方法吗?

在Java中(以及很多其他面向对象的编程语言中),静态方法属于类级别的方法,而不是实例级别的方法。当我们在抽象类中定义一个静态方法时,这个方法可以被类直接调用,而不是由类的实例调用。因此,虽然Square继承自Shape,它继承的是Shape的非静态行为和属性。静态方法getShape可以通过类名直接调用,如Shape.getShape("CIRCLE"),而不是通过一个ShapeSquare的实例来调用。

所以,从概念上讲,Square类并不会“拥有”getShape方法。getShape是属于Shape类的,尽管SquareShape的一个子类。这并不会导致混乱,因为静态方法的调用总是明确指向它们所属的类。

  1. 实体类可以调用静态方法吗?

实体类(或者说任何类)可以调用静态方法,但调用方式与实例方法不同。静态方法通过类本身来调用,而不是通过类的实例。这意味着,即使你有一个Shape类的实例,你也应该使用类名来调用静态方法,比如Shape.getShape("CIRCLE"),而不是使用实例来调用。这是因为静态方法不依赖于类的任何特定实例。

  1. Shape是抽象类可以被实例化吗?

抽象类不能被直接实例化。抽象类的目的是为其他类提供一个共同的、被继承的类型框架,定义一些可以在多个子类中共享的方法和属性。你不能创建一个抽象类Shape的实例,但你可以创建它的子类(如CircleSquare)的实例,这些子类提供了抽象方法的具体实现。静态方法getShape提供了一种机制,允许你根据输入的参数类型创建并返回具体子类的实例,而无需直接实例化抽象类。

简而言之,虽然Shape是一个抽象类且不能被实例化,但Shape类中的静态方法getShape提供了一种创建和返回Shape子类实例的方式,而这一切并不需要直接实例化抽象类Shape本身。

  • 标题: 工厂模式内容补充理解
  • 作者: SYuan03
  • 创建于 : 2024-03-25 20:05:11
  • 更新于 : 2024-03-25 20:07:55
  • 链接: https://bblog.031105.xyz/posts/软件系统设计/工厂模式内容补充理解.html
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论