简单工厂模式(Simple Factory Pattern)
定义:简单工厂模式不属于GoF的23种设计模式之一,但它是一种常见的创建型模式。通过简单工厂,一个工厂类根据输入的参数,决定创建哪一个具体类的实例。
关键点
- 工厂类:负责创建实例的逻辑。
- 产品类:所有被创建的类的父类或接口。
- 参数:决定实例化哪个具体类。
优点
- 封装对象创建:将对象创建的逻辑集中在一个地方,简化代码。
- 便于管理:创建对象的逻辑统一管理,便于修改和维护。
缺点
- 单一职责原则:工厂类承担了过多职责,既负责创建对象,又包含选择逻辑。
- 扩展困难:每次增加新类型时,都需要修改工厂类的代码。
改进方向:
- 工厂方法模式:将工厂类的职责分解为多个具体工厂,每个工厂负责创建一种类型的对象。
- 抽象工厂模式:提供接口以创建一系列相关或依赖的对象,而无需指定它们的具体类。
一、代码实现
假设我们有一个图形接口 Shape
,以及其实现类 Circle
和 Rectangle
。通过简单工厂模式,我们可以根据需求创建具体的图形对象。
定义产品接口和具体产品类
-
Shape.java:图形接口
public interface Shape { void draw(); }
-
Circle.java:具体的圆形类
public class Circle implements Shape { @Override public void draw() { System.out.println("Drawing a Circle"); } }
-
Rectangle.java:具体的矩形类
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Drawing a Rectangle"); } }
定义工厂类
- ShapeFactory.java:工厂类
public class ShapeFactory { // 静态方法,根据输入参数创建具体图形对象 public static Shape createShape(String shapeType) { if (shapeType == null || shapeType.isEmpty()) { return null; } if ("CIRCLE".equalsIgnoreCase(shapeType)) { return new Circle(); } else if ("RECTANGLE".equalsIgnoreCase(shapeType)) { return new Rectangle(); } return null; } }
测试工厂类
- Main.java:测试类
public class Main { public static void main(String[] args) { // 使用工厂类创建图形对象 Shape shape1 = ShapeFactory.createShape("CIRCLE"); shape1.draw(); Shape shape2 = ShapeFactory.createShape("RECTANGLE"); shape2.draw(); // 测试无效输入 Shape shape3 = ShapeFactory.createShape("TRIANGLE"); if (shape3 != null) { shape3.draw(); } else { System.out.println("This shape type is not supported."); } } }
二、JDK中的运用
NumberFormat
private static NumberFormat getInstance(LocaleProviderAdapter adapter,
Locale locale, int choice) {
NumberFormatProvider provider = adapter.getNumberFormatProvider();
NumberFormat numberFormat = null;
switch (choice) {
case NUMBERSTYLE:
numberFormat = provider.getNumberInstance(locale);
break;
case PERCENTSTYLE:
numberFormat = provider.getPercentInstance(locale);
break;
case CURRENCYSTYLE:
numberFormat = provider.getCurrencyInstance(locale);
break;
case INTEGERSTYLE:
numberFormat = provider.getIntegerInstance(locale);
break;
}
return numberFormat;
}