在软件设计中,我们经常遇到需要创建不同类型对象的情况,但是如果直接在代码中实例化对象,会使代码紧密耦合在一起,难以维护和拓展,此外,如果对象的创建方式需要变化,那么就需要再整个代码中进行大量的修改。工厂模式旨在解决这个问题。
工厂模式提供了一个创建对象的接口,但是将具体的对象创建延迟到子类中。这样,客户端代码不需要知道要创建的具体对象的类,只需要通过工厂方法来创建对象。这使得客户端代码与具体对象的创建解耦,提高了代码的灵活性和可维护性。工厂模式中,通常会定义一个抽象工厂类,其中包含一个创建对象的抽象方法,而具体的对象创建则由具体的子类实现。这样每个具体的子类都可以根据需要创建不同类型的对象,而客户端代码只需要通过抽象工厂类来调用工厂方法而不需要关心具体的对象创建细节。
工厂模式的优点包括:
- 松耦合:客户端代码与具体对象的创建解耦,使得系统更具弹性和可维护性。
- 扩展性:通过添加新的具体工厂和产品子类,可以很容易的扩展系统以支持新的对象类型。
- 封装性:将对象的创建集中在工厂类中,封装了对象的创建细节,使得客户端代码更简洁。
工厂模式的缺点包括:
- 工厂模式会增加系统中类的数量,当产品类型较多时,会导致系统过于庞大和复杂。
- 工厂模式需要引入抽象层,这会增加系统的抽象性和理解难度。
- 工厂模式可能会导致类层次过多,增加系统设计难度。
然而,工厂模式也可能引入一些额外的复杂性,因为需要定义多个工厂类和产品类的层次结构,这可能为导致系统中类的数量增加。在选择使用工厂方法模式时,需要根据具体情况进行权衡。工厂模式在实际应用中非常常见,例如,图形库可以使用工厂方法模式来创建不同类型的图形对象,数据库访问框架可以使用工厂模式来创建不同类型的数据库连接等。
工厂模式下又分简单工厂模式和工厂方法模式:
简单工厂模式代码实例:
// Shape接口
public interface Shape {
void draw();
}
// Circle类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Draw a circle");
}
}
// Rectangle类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Draw a rectangle");
}
}
// Square类
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Draw a square");
}
}
// ShapeFactory类
public class ShapeFactory {
// 静态方法createShape
public static Shape createShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("circle")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("rectangle")) {
return new Rectangle();
} else if (shapeType.equalsIgnoreCase("square")) {
return new Square();
}
return null;
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// 创建一个圆形对象
Shape circle = ShapeFactory.createShape("circle");
// 调用圆形对象的draw方法
circle.draw();
// 创建一个矩形对象
Shape rectangle = ShapeFactory.createShape("rectangle");
// 调用矩形对象的draw方法
rectangle.draw();
// 创建一个正方形对象
Shape square = ShapeFactory.createShape("square");
// 调用正方形对象的draw方法
square.draw();
}
}
上面的例子中定义了一个Shape接口和三个实现类:Circle,Rectangle,Square,然后定义了ShapeFactory类,并给他定义了一个静态方法createShape,可以根据掺入参数来返回相应的对象。最后我们在客户端使用ShapeFactory来创建不同类型的对象。简单工厂模式实际上就是将实例化类抽离出来,通过传参的形式来判断需要创建哪一个类,并交给工厂类去创建。
工厂方法模式代码实例:
// Shape接口
public interface Shape {
void draw();
}
// Circle类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Draw a circle");
}
}
// Rectangle类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Draw a rectangle");
}
}
// Square类
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Draw a square");
}
}
// 抽象工厂类ShapeFactory
public abstract class ShapeFactory {
// 抽象方法createShape
public abstract Shape createShape();
}
// CircleFactory类
public class CircleFactory extends ShapeFactory {
@Override
public Shape createShape() {
return new Circle();
}
}
// RectangleFactory类
public class RectangleFactory extends ShapeFactory {
@Override
public Shape createShape() {
return new Rectangle();
}
}
// SquareFactory类
public class SquareFactory extends ShapeFactory {
@Override
public Shape createShape() {
return new Square();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// 创建一个圆形工厂对象
ShapeFactory circleFactory = new CircleFactory();
// 通过圆形工厂对象创建一个圆形对象
Shape circle = circleFactory.createShape();
// 调用圆形对象的draw方法
circle.draw();
// 创建一个矩形工厂对象
ShapeFactory rectangleFactory = new RectangleFactory();
// 通过矩形工厂对象创建一个矩形对象
Shape rectangle = rectangleFactory.createShape();
// 调用矩形对象的draw方法
rectangle.draw();
// 创建一个正方形工厂对象
ShapeFactory squareFactory = new SquareFactory();
// 通过正方形工厂对象创建一个正方形对象
Shape square = squareFactory.createShape();
// 调用正方形对象的draw方法
square.draw();
}
}
与简单工厂模式不同的是,工厂方法模式没有把不同的类都交给一个工厂去创建,而是针对每个类分别定义了一个工厂类来创建自己的对象,这里分别是:CircleFactory类,RectangleFactory类,SquareFactory类,最后就可以在客户端Client中,通过实例化不同的工厂类来创建不同的对象,在实际场景中,Mybaits中的SqlSessionFactory就是一个典型的简单工厂模式,他会根据传入参数的不同返回SqlSession,再通过SqlSession来执行SQL。