好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受.
工厂方法模式是java中非常经典的设计模式,如下将好好讲解下java设计模式相关的知识。
工厂方法模式的前世今生
-
起源 :工厂方法模式是一种创建型设计模式,其产生源于软件开发中对对象创建过程的封装需求。在早期的软件开发中,对象的创建往往直接通过
new
关键字在代码中硬编码实现,这种方式虽然简单直接,但在面对复杂的对象创建逻辑、需要解耦创建与使用、以及扩展新的对象类型时,会导致代码的修改频繁、可维护性差等问题。 -
演变与现状 :为了解决这些问题,工厂方法模式应运而生。它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,将对象的创建逻辑封装到子类中,从而实现了对象创建的解耦。如今,工厂方法模式已经成为了设计模式中的经典模式之一,在众多软件系统中得到了广泛的应用,尤其是在需要频繁创建对象且对象类型可能扩展的场景中,如框架的开发、插件系统的实现等。
工厂方法模式的使用场景
-
创建对象需要大量重复代码 :当在代码中多次出现通过
new
关键字创建同一类对象的代码时,使用工厂方法模式可以将这些重复的创建代码封装到工厂类中,提高代码的复用性和可维护性。 -
解耦对象的创建和使用 :如果希望代码在使用对象时,不需要关心对象的创建过程,只是通过一个统一的接口来获取对象实例,那么工厂方法模式就非常适合。这样可以使代码更加模块化,降低对象创建和使用之间的耦合度,提高系统的灵活性和可扩展性。
-
创建对象的过程较为复杂 :当创建对象的过程涉及到多个步骤,或者需要根据不同条件创建不同的对象时,工厂方法模式可以帮助将这些复杂的创建逻辑集中到工厂类中进行处理,使得客户端代码可以更加简洁和专注于对象的使用,而不是被复杂的创建细节所困扰。
-
需要支持动态扩展对象类型 :如果在系统运行期间,可能会根据不同的需求动态地添加新的对象类型,那么使用工厂方法模式可以在不修改现有客户端代码的情况下,通过增加新的工厂子类来支持新对象类型的创建,符合开闭原则,方便系统的扩展和维护。
工厂方法模式使用的注意事项
-
避免过度使用 :虽然工厂方法模式有很多优点,但并不意味着在所有需要创建对象的场景下都要使用它。如果场景中对象的创建过程非常简单,且没有明显的扩展需求,那么直接使用
new
关键字创建对象可能更加简单高效,使用工厂方法模式反而会增加不必要的复杂性和代码量。 -
合理设计工厂类和产品类的层次结构 :在设计工厂方法模式时,需要合理地划分工厂类和产品类的层次结构。工厂类和产品类之间应该保持紧密的关联性,每个工厂类通常对应一类产品类,不同的工厂类之间应该尽量避免功能重叠和代码冗余。同时,产品类的设计也要遵循一定的规范,尽量保持接口的一致性和兼容性,以便在客户端代码中能够方便地使用不同的产品对象。
-
考虑线程安全性 :如果工厂方法模式在多线程环境下使用,需要确保工厂类的线程安全性。例如,当工厂类中存在一些共享的资源或状态时,需要通过适当的同步机制来保证在多线程并发创建对象时不会出现数据不一致或异常的情况。
-
可扩展性与灵活性的平衡 :在设计工厂方法模式时,既要考虑到系统的可扩展性,以便能够方便地添加新的产品类型,又要兼顾代码的简洁性和可读性。如果为了追求极致的可扩展性而设计过于复杂和繁琐的工厂类层次结构,可能会导致代码难以理解和维护,因此需要在可扩展性和灵活性之间找到一个平衡点。
工厂方法模式的代码样例
-
简单示例 :
// 抽象产品类
interface Shape {
void draw();
}
// 具体产品类:圆形
class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 具体产品类:矩形
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 抽象工厂类
abstract class ShapeFactory {
public abstract Shape createShape();
}
// 具体工厂类:创建圆形工厂
class CircleFactory extends ShapeFactory {
@Override
public Shape createShape() {
return new Circle();
}
}
// 具体工厂类:创建矩形工厂
class RectangleFactory extends ShapeFactory {
@Override
public Shape createShape() {
return new Rectangle();
}
}
// 客户端代码
public class FactoryMethodExample {
public static void main(String[] args) {
// 使用圆形工厂创建圆形对象并调用其方法
ShapeFactory circleFactory = new CircleFactory();
Shape circle = circleFactory.createShape();
circle.draw();
// 使用矩形工厂创建矩形对象并调用其方法
ShapeFactory rectangleFactory = new RectangleFactory();
Shape rectangle = rectangleFactory.createShape();
rectangle.draw();
}
}
-
示例说明 :在这个示例中,我们定义了一个抽象产品类
Shape
,它有一个draw()
方法。然后,我们创建了两个具体产品类Circle
和Rectangle
,分别实现了Shape
接口。接着,我们定义了一个抽象工厂类ShapeFactory
,它声明了一个createShape()
方法用于创建Shape
对象。最后,我们创建了两个具体工厂类CircleFactory
和RectangleFactory
,它们分别实现了ShapeFactory
接口,并在createShape()
方法中返回对应的Circle
和Rectangle
对象。在客户端代码中,我们通过具体的工厂类来创建产品对象,并调用它们的方法。通过这种方式,客户端代码不需要直接使用new
关键字来创建对象,而是通过工厂类来获取对象实例,实现了对象创建和使用的解耦。同时,如果需要添加新的形状类型,如三角形,只需要新增一个三角形的实现类和对应的工厂类,而不需要修改现有的客户端代码,满足了开闭原则。