在软件开发领域,设计模式是一种被广泛应用的解决方案,它可以帮助开发者解决常见的问题,我们将重点讨论一种被称为“建造者模式”的设计模式,建造者模式是一种创建型设计模式,它提供了一种将一个复杂对象的构建与其表示分离的方法,使得同样的构建过程可以创建不同的表示,这种模式通常用于创建具有多个组成部分的对象,尤其是当这些部分之间的关系不固定或者需要经常改变时。
让我们来了解一下建造者模式的基本概念,建造者模式主要包括以下几个部分:
1、抽象建造者(Builder):这是一个抽象类,它定义了创建对象所需的所有方法,但不包含具体的实现,抽象建造者的主要目的是为子类提供一个通用的接口,以便在子类中实现具体的创建过程。
2、具体建造者(ConcreteBuilder):这是继承自抽象建造者的一类特殊子类,它实现了抽象建造者中定义的所有方法,具体建造者负责根据输入的数据创建对象的各个组成部分。
3、指挥者(Director):这是一个接口,它定义了一个名为build的方法,用于接收具体建造者的输出并将其组合成一个完整的对象,指挥者的主要目的是协调具体建造者的工作,确保对象的正确构建。
4、产品(Product):这是我们需要构建的对象,它由指挥者负责创建,产品类通常是一个简单的数据结构,如一个复杂的自定义类。
下面我们通过一个简单的例子来说明如何使用建造者模式,假设我们需要创建一个表示二维点的对象,这个对象包含两个属性:x坐标和y坐标,我们可以使用建造者模式来实现这个需求。
我们定义一个表示二维点的抽象类Point
:
public abstract class Point { protected int x; protected int y; public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public abstract void draw(); }
我们定义一个具体的二维点类ConcretePoint
,它继承自抽象类Point
:
public class ConcretePoint extends Point { @Override public void draw() { System.out.println("Drawing a point at (" + x + ", " + y + ")"); } }
我们定义一个表示二维点组成部分的具体建造者类CoordinateBuilder
,它继承自抽象建造者类CoordinateBuilder
:
public abstract class CoordinateBuilder { protected int x; protected int y; public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } }
我们定义两个具体的坐标建造者类:XCoordinateBuilder
和YCoordinateBuilder
,它们分别负责创建x坐标和y坐标:
public class XCoordinateBuilder extends CoordinateBuilder { private ConcretePoint concretePoint; public XCoordinateBuilder(ConcretePoint concretePoint) { this.concretePoint = concretePoint; } @Override public void build() { concretePoint.setX(x); } }
public class YCoordinateBuilder extends CoordinateBuilder { private ConcretePoint concretePoint; public YCoordinateBuilder(ConcretePoint concretePoint) { this.concretePoint = concretePoint; } @Override public void build() { concretePoint.setY(y); } }
我们定义一个指挥者类PointDirector
,它负责协调具体建造者的工作:
public class PointDirector implements Director<ConcretePoint> { private List<CoordinateBuilder> builders; int count = 0; // 需要的坐标数量减1,因为coordinates已经默认设置为0了,例如对于(3,4),count为2而不是3,所以这里应该是count-1=2,如果有更多的坐标参数传入,那么count应该增加相应的值,否则就会出错,这也是为什么我们在构造函数中初始化builders的原因,这样就可以保证所有的坐标都已经准备好了,而且由于我们的builders列表是不可变的,所以即使添加新的坐标也不会影响到其他坐标的构建过程。