工厂模式(Factory)

简介: 工厂模式是创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,创建对象不会对客户端暴露创建逻辑,隐藏创建对象的详情,从而实现客户端与具体实现的解耦。工厂模式设计时需求注意的点:工厂类提供公共的方法来创建对象,无论静态,而不是客户端直接创建方法的参数可选,但参数只用来决定哪种实现,不应该存在业务参数方法的返回一般是被创建的接口对象,也可以是抽象类或具体类常见的工厂模式有工厂方法模式、简单工厂模式和抽象工厂模式等,并不要拘泥于哪种,在实际业务中根据需求设计。


一、概述



工厂模式是创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,创建对象不会对客户端暴露创建逻辑,隐藏创建对象的详情,从而实现客户端与具体实现的解耦。工厂模式设计时需求注意的点:

  • 工厂类提供公共的方法来创建对象,无论静态,而不是客户端直接创建
  • 方法的参数可选,但参数只用来决定哪种实现,不应该存在业务参数
  • 方法的返回一般是被创建的接口对象,也可以是抽象类或具体类

常见的工厂模式有工厂方法模式、简单工厂模式和抽象工厂模式等,并不要拘泥于哪种,在实际业务中根据需求设计。


二、工厂方法



工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。在代码中,使用不同的工厂子类创建不同的对象,创建对象的细节封装在子类中。比如我们使用工厂方法来实现绘制不同形状的图形。

微信图片0001.jpg

定义一个 Shape 接口,并添加实现类,编写示例代码如下:

// Shape.java
public interface Shape {
    void draw();
}
// Circle.java
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Circle.draw");
    }
}
// Rectangle.java
public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Rectangle.draw");
    }
}
// Square.java
public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Square.draw");
    }
}

针对 Shape 接口定义一个抽象工厂类 ShapeFactory,并添加各个实例类的工厂子类,编写代码如下:

// ShapeFactory.java
public abstract class ShapeFactory {
    public void operate() {
        Shape shape = factoryMethod();
        shape.draw();
    }
    // 将创建对象的细节交给子类
    protected abstract Shape factoryMethod();
}
// CircleFactory.java
public class CircleFactory extends ShapeFactory {
    @Override
    protected Shape factoryMethod() {
        return new Circle();
    }
}
// RectangleFactory.java
public class RectangleFactory extends ShapeFactory {
    @Override
    protected Shape factoryMethod() {
        return new Rectangle();
    }
}
// SquareFactory.java
public class SquareFactory extends ShapeFactory {
    @Override
    protected Shape factoryMethod() {
        return new Square();
    }
}

编写主方法类,运行示例代码:

// Main.java
public class Main {
    public static void main(String[] args) {
        new CircleFactory().operate();
        new RectangleFactory().operate();
        new SquareFactory().operate();
    }
}


三、简单工厂



简单工厂模式(Factory)定义用于创建对象的类,客户端调用工厂类方法(静态或非静态)根据参数类型创建不同的对象实例,从而使得客户端和实现之间解耦。比如我们使用简单静态工厂来绘制不同形状的图形。

微信图片0002.png

定义一个工厂类,添加静态方法来根据类型创建不同实例,编写代码如下:

public class ShapeFactory {
    public static Shape getShape(String shapeType) {
        if ("CIRCLE".equalsIgnoreCase(shapeType)) {
            return new Circle();
        }
        if ("RECTANGLE".equalsIgnoreCase(shapeType)) {
            return new Rectangle();
        }
        if ("SQUARE".equalsIgnoreCase(shapeType)) {
            return new Square();
        }
        return null;
    }
}

编写主方法类,运行示例代码:

public class Main {
    public static void main(String[] args) {
        Shape circle = ShapeFactory.getShape("CIRCLE");
        circle.draw();
        Shape rectangle = ShapeFactory.getShape("RECTANGLE");
        rectangle.draw();
        Shape square = ShapeFactory.getShape("SQUARE");
        square.draw();
    }
}

简单工厂与工厂方法不一样的地方是简单工厂是客户端根据方法的参数类型来创建不同的对象。参数类型可以是整型数据、字符串等基本数据类型,也可以是枚举或其他类型,只要可以区分创建对象的实例类型就行,我们也可以利用环境配置,或者某个 Profile 来确定创建的对象实例,以达到兼容的目的。


四、抽象工厂



微信图片0003.png

抽象工厂模式(Abstract Factory)和工厂模式很相似,抽象工厂对工厂类进行了一层抽象,抽象的工厂类(超级工厂)可以创建其他工厂。比如我们基于前面的例子绘制不同形状的图形,并且给图形填充不同的颜色

定义一个 Color 颜色接口,并添加实现类,编写示例代码如下:

// Color.java
public interface Color {
    void fill();
}
// Red.java
public class Red implements Color {
    @Override
    public void fill() {
        System.out.println("Red.fill");
    }
}
// Green.java
public class Green implements Color {
    @Override
    public void fill() {
        System.out.println("Green.fill");
    }
}
// Blue.java
public class Blue implements Color {
    @Override
    public void fill() {
        System.out.println("Blue.fill");
    }
}

定义一个抽象工厂,并添加形状和颜色的实现工厂类,编写代码如下:

// AbstractFactory.java
public abstract class AbstractFactory {
    public abstract Color getColor(String color);
    public abstract Shape getShape(String shape);
}
// ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
    @Override
    public Shape getShape(String shape) {
        if ("CIRCLE".equalsIgnoreCase(shape)) {
            return new Circle();
        } else if ("RECTANGLE".equalsIgnoreCase(shape)) {
            return new Rectangle();
        } else if ("SQUARE".equalsIgnoreCase(shape)) {
            return new Square();
        }
        return null;
    }
    @Override
    public Color getColor(String color) {
        return null;
    }
}
// ColorFactory.java
public class ColorFactory extends AbstractFactory {
    @Override
    public Color getColor(String color) {
        if ("RED".equalsIgnoreCase(color)) {
            return new Red();
        } else if ("GREEN".equalsIgnoreCase(color)) {
            return new Green();
        } else if ("BLUE".equalsIgnoreCase(color)) {
            return new Blue();
        }
        return null;
    }
    @Override
    public Shape getShape(String shape) {
        return null;
    }
}

定义超级工厂类,用于生产工厂类,编写代码如下:

// FactoryProducer.java
public class FactoryProducer {
    public static AbstractFactory getFactory(String choice) {
        if ("SHAPE".equalsIgnoreCase(choice)) {
            return new ShapeFactory();
        } else if ("COLOR".equalsIgnoreCase(choice)) {
            return new ColorFactory();
        }
        return null;
    }
}

编写主方法类,运行示例代码

// Main.java
public class Main {
    public static void main(String[] args) {
        AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
        Shape shape;
        shape = shapeFactory.getShape("CIRCLE");
        shape.draw();
        shape = shapeFactory.getShape("RECTANGLE");
        shape.draw();
        shape = shapeFactory.getShape("SQUARE");
        shape.draw();
        AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
        Color color;
        color = colorFactory.getColor("RED");
        color.fill();
        color = colorFactory.getColor("GREEN");
        color.fill();
        color = colorFactory.getColor("BLUE");
        color.fill();
    }
}

抽象工厂模式基于简单工厂模式又对工厂进行了一层抽象,将工厂类也以工厂的形式创建。


五、Spring实现工厂



Spring容器管理一个接口的多个实现类Bean时,可以使用 Map 形式注入所有实现类的Bean,这个Map的Key为注册Bean的BeanName,Map的Value为对应的Bean。所以我们可以利用这个特性使用Spring的IoC功能实现一个工厂模式,还是使用前面的示例。

Spring 默认注册的 BeanName 一般为类名的小驼峰形式,也可以自己指定。

定义一个 Shape 接口,并添加实现类,此时所有的实现类交给Spring管理,编写代码如下:

// Shape.java
public interface Shape {
    void draw();
}
// Circle.java
@Service
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Circle.draw");
    }
}
// Rectangle.java
@Service
public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Rectangle.draw");
    }
}
// Square.java
@Service
public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Square.draw");
    }
}




定义一个工厂类,也要交给Spring管理,然后使用 Map 注入需要生产的Bean,编写代码如下:

// ShapeFactory.java
@Service
public class ShapeFactory {
    private static Map<String, Shape> shapeMap;
    public static Shape getShape(String beanName) {
        return shapeMap.get(beanName);
    }
    @Autowired
    public void setShapeMap(Map<String, Shape> shapeMap) {
        ShapeFactory.shapeMap = shapeMap;
    }
}

编写主方法类,定义ApplicationContext并扫描前面注册Bean所在的包,编写代码如下:

// Main.java
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext("com.ajn.spring.factory");
        Shape circle = ShapeFactory.getShape("circle");
        circle.draw();
        Shape rectangle = ShapeFactory.getShape("rectangle");
        rectangle.draw();
        Shape square = ShapeFactory.getShape("square");
        square.draw();
    }
}


目录
相关文章
|
9月前
|
前端开发 JavaScript Java
基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】
基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】
297 0
|
消息中间件 JSON 负载均衡
feign 调用常见问题避坑指南!
feign 调用常见问题避坑指南!
feign 调用常见问题避坑指南!
|
9月前
|
缓存 前端开发 JavaScript
探索 Rollup:简化你的前端构建流程
探索 Rollup:简化你的前端构建流程
探索 Rollup:简化你的前端构建流程
|
运维 监控 Java
MyBatisPlus的in方法入参数量过多导致的JVM频繁FullGC案例
MyBatisPlus的in方法入参数量过多导致的JVM频繁FullGC案例
801 0
|
Java Spring
spring boot 整合七牛云简单使用
spring boot 整合七牛云简单使用
624 0
spring boot 整合七牛云简单使用
【精彩活动预告】第十二届 BigData NoSQL Meetup (北京站)大咖云集,与你畅聊BigData NoSQL
云栖开发者沙龙介绍​ 阿里云栖开发者沙龙是“云栖社区”主办的线下技术沙龙品牌,希望通过技术干货分享来打通线上线下专家和开发者的连接。沙龙每期将定位不同的技术方向,逐步覆盖 云计算,大数据,前端,PHP,Java ,android,AI,运维,测试 等技术领域,并会穿插一些特别专场(开源专场,女性开发者专场,开发者成长专场等)。
16304 0
|
9月前
|
JSON 前端开发 数据可视化
AMIS【部署 01】amis前端低代码框架可视化编辑器amis-editor本地部署流程
AMIS【部署 01】amis前端低代码框架可视化编辑器amis-editor本地部署流程
1264 0
|
前端开发
Vue3树形控件实现跳转页面
今天想分享的是Vue3中利用element-plus中的树形控件实现跳转页面,做成类似标签页tabs一样的效果。
503 4
Vue3树形控件实现跳转页面
|
开发工具 git
git查看最近提交的代码历史记录
git查看最近提交的代码历史记录 查看最近一天的代码提交情况: git log --since=1.days 查看最近一周的代码提交情况: git log --since=1.
3525 0

热门文章

最新文章