简单工厂模式、工厂方法模式、抽象工厂模式 对比学习笔记

工厂模式

架构设计原则

开闭原则:是指一个软件实体(如类、模块和函数)应该对扩展开放,对修改关闭。

依赖倒置原则:是指设计代码结构时,高层模块不应该依赖低层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。

单一职责:是指一个类只负责一个主要任务,避免因一个类负责两个以上任务时,修改其中一个任务代码导致另一个任务代码受到连带影响。

接口隔离原则:是指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口

迪米特原则:是指一个对象应该对其他对象保持最少的了解,又叫最少知道原则,尽量降低类与类之间的耦合度。

里氏替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能。

合成复用原则:是指尽量使用对象组合,而不是继承关系达到软件复用的目的。

工厂模式是创建型模式,这种模式的特点是可以将对象的创建和使用相分离,适用于对象的创建比较复杂,希望对外隐藏对象的创建过程的场景。同时由于对象的创建和使用相分离,使得逻辑代码与对象的创建解耦,方便管理对象。

具体的实现方法上有三种模式,分别是:简单工厂模式(Simple Factory Pattern)、工厂方法模式(Factory Method Pattern)、抽象工厂模式(Abstract Factory Pattern)。

简单工厂模式

简单工厂模式适用于:对象的创建逻辑简单,对象的继承关系相对简单,需要被工厂方法创建的对象数量较少的情况。

简单工厂模式中的角色分工:
  • 工厂类:负责创建用户所需的产品对象。
  • 产品接口:是简单工厂创建的所有对象的父类,描述了具体产品类的所有公共属性。
  • 具体的产品类:被简单工厂模式创建的对象,是产品接口的不同具体实现类。

例如:在学校我们要学习多种课程,我们就可以定义一个课程类接口,不同的课程教授不同的内容,于是我们有了JavaCourse子类、和PythonCourse子类。

代码演示

定义Course接口:

public interface Course {
    void recode();
}

定义Course接口子类JavaCourse

public class JavaCourse implements Course{
    @Override
    public void recode() {
        System.out.println("Java课程正在录制");
    }
}

定义Course接口子类PythonCourse

public class PythonCourse implements Course{
    @Override
    public void recode() {
        System.out.println("Python课程正在录制");
    }
}

定义CourseType枚举类,方便告诉工厂我们需要的对象类型。

public enum CourseType {
    JAVA_COURSE,PYTHON_COURSE;
}

定义工厂

public class CourseFactory {
    public static Course createCourse(CourseType courseType){
        switch(courseType){
            case JAVA_COURSE: return new JavaCourse();
            case PYTHON_COURSE: return new PythonCourse();
            default: return null;
        }
    }
}

测试方法

public class Client {
    public static void main(String[] args) {
        Course javaCourse = CourseFactory.createCourse(CourseType.JAVA_COURSE);
        Course pythonCourse = CourseFactory.createCourse(CourseType.PYTHON_COURSE);
        javaCourse.recode();
        pythonCourse.recode();
    }
}

测试结果如下

简单工厂模式、工厂方法模式、抽象工厂模式 对比学习笔记_第1张图片

简单工厂模式、工厂方法模式、抽象工厂模式 对比学习笔记_第2张图片

简单工厂模式的优点:

​ 可以将对象的创建与逻辑代码解耦,方便后期的代码维护。

简单工厂模式的缺点:

​ 所有的产品类都在一个工厂中产生,工厂类的职责相对过重,不易于扩展过于复杂的产品结构。

工厂方法模式

工厂方法模式主要解决的是产品扩展问题,当随着产品类数量的增多,每个产品类的实例化逻辑也各不相同时,如果再将所有的产品类实例化过程都集中在一个工厂方法中,就会使得该方法变得巨大无比,不利用程序的维护和可读性。

工厂方法模式的解决思路是:工厂父类定义统一的接口,为每一种产品类单独定义一个创造工厂,由调用者决定具体调用哪个工厂方法。

工厂方法模式适用于:对象的创建逻辑复杂,或经常需要增添新的类。

工厂方法模式中的角色分工:
  • 工厂接口:定义了生产产品的方法,但没有具体的实现该方法,方法的实现交给具体的工厂子类实现。
  • 具体的工厂子类:实现了工厂接口中定义的生产产品的方法,负责生产具体的产品对象。
  • 产品接口:具体产品类的父类,描述了具体产品的所有公共属性。
  • 具体的产品类:产品接口的具体实现,是被工厂创建的对象。
代码演示

定义课程类接口

public interface Course {
    void recode();
}

定义JavaCourse子类

public class JavaCourse implements Course{
    @Override
    public void recode() {
        System.out.println("Java课程正在录制");
    }
}

定义PythonCourse子类

public class PythonCourse implements Course{
    @Override
    public void recode() {
        System.out.println("Python课程正在录制");
    }
}

定义工厂接口

public interface CourseFactory {
    Course createCourse();
}

定义JavaCourseFactory

public class JavaCourseFactory implements CourseFactory{
    @Override
    public Course createCourse() {
        return new JavaCourse();
    }
}

定义PythonCourseFactory

public class PythonCourseFactory implements CourseFactory{
    @Override
    public Course createCourse() {
        return new PythonCourse();
    }
}

测试类

public class Client {
    public static void main(String[] args) {
        CourseFactory javaCourseFactory = new JavaCourseFactory();
        CourseFactory pythonCourseFactory = new PythonCourseFactory();
        Course javaCourse = javaCourseFactory.createCourse();
        Course pythonCourse = pythonCourseFactory.createCourse();
        javaCourse.recode();
        pythonCourse.recode();
    }
}

测试结果

简单工厂模式、工厂方法模式、抽象工厂模式 对比学习笔记_第3张图片

关系类图:

简单工厂模式、工厂方法模式、抽象工厂模式 对比学习笔记_第4张图片

​ 工厂方法模式需要创建对应的课程工厂实例,才能获取到对应课程对象。可能会有小伙伴觉得这不是脱了裤子放屁——多此一举吗?明明可以直接new 一个我们需要的课程对象。其实是因为这个例子比较简单,通常工厂方法模式用于对象的创建逻辑比较复杂,代码繁琐的场景。

​ 如JDBC常用的PreparedStatement对象,还记得创建PreparedStatemenet对象的步骤吗?

​ 加载驱动–>连接数据库–>获取Connection对象–>获取PreparedStatement对象。

运用工厂方法模式就可以将这些步骤封装起来,简化程序代码。

工厂方法模式的优点:

​ 方便产品扩展,工厂类的职责清晰,结构简单。例如我如果想在项目中添加一个linux课程,只需要在项目中添加一个LinuxCourse类,和LinuxCourseFactory类即可,不用对之前的代码做任何修改。

工厂方法模式的缺点:

​ 每种产品类都对应着一种工厂类,当商品的种类增多时,维护起来有一定难度。

抽象工厂模式

工厂方法模式中只有一个抽象方法,要想获得不同类型的产品对象,就要创建不同的工厂子类对象,而抽象工厂则是让一个工厂负责创建多个不同类型的对象。

抽象工厂模式适用于:需要一组对象共同完成某种功能时,并且可能存在多组对象完成不同功能的情况。(同属于同一个产品族的产品);系统结构稳定,不会频繁的增加对象。

抽象工厂方法模式角色分工:
  • 工厂接口:定义了各种产品的生产方法,具体的方法实现交由工厂子类实现。
  • 工厂子类:实现工厂接口中定义的方法,负责生产某一类产品对象。
  • 产品接口:具体产品类的父类,描述了具体产品的所有公共属性。
  • 具体的产品类:产品接口的具体实现,是被工厂创建的对象。

​ 接着上面的例子,现在学校不仅要求老师们上课,还要提供课程录像和课堂笔记,这样就有java视频类,python视频类,java笔记类,python笔记类,四个类;如果还采取工厂方法模式就需要四个工厂方法类;随着课程数量的增多,工厂方法的数量也会增多,最终会变得臃肿,难以维护。

​ 而使用抽象工厂模式,只需要两个工厂方法即可。

代码演示

定义Note接口

public interface Note {
    void show();
}

定义JavaNote实现类

public class JavaNote implements Note{
    @Override
    public void show() {
        System.out.println("这是Java的笔记");
    }
}

定义PythonNote实现类

public class PythonNote implements Note{
    @Override
    public void show() {
        System.out.println("这是Python的笔记");
    }
}

定义Video接口

public interface Video {
    void play();
}

定义JavaVideo实现类

public class JavaVideo implements Video{
    @Override
    public void play() {
        System.out.println("正在播放Java的视频");
    }
}

定义PythonVideo实现类

public class PythonVideo implements Video{
    @Override
    public void play() {
        System.out.println("正在播放Python的视频");
    }
}

定义Factory接口

public interface Factory {
    Note createNote();
    Video createVideo();
}

定义JavaFactory

public class JavaFactory implements Factory{
    @Override
    public Note createNote() {
        return new JavaNote();
    }

    @Override
    public Video createVideo() {
        return new JavaVideo();
    }
}

定义PythonFactory实现类

public class PythonFactory implements Factory {
    @Override
    public Note createNote() {
        return new PythonNote();
    }

    @Override
    public Video createVideo() {
        return new PythonVideo();
    }
}

测试类

public class Client {
    public static void main(String[] args) {
        Factory javaFactory = new JavaFactory();
        Factory pythonFactory = new PythonFactory();

        Note javaNote = javaFactory.createNote();
        Video javaVideo = javaFactory.createVideo();

        Note pythonNote = pythonFactory.createNote();
        Video pythonVideo = pythonFactory.createVideo();

        javaNote.show();
        javaVideo.play();

        pythonNote.show();
        pythonVideo.play();

    }
}

运行结果

简单工厂模式、工厂方法模式、抽象工厂模式 对比学习笔记_第5张图片

关系类图

简单工厂模式、工厂方法模式、抽象工厂模式 对比学习笔记_第6张图片

抽象工厂模式的优点:
  1. 一个工厂类可以创建一个系类的多个对象,简化了获取产品对象的复杂度 。
  2. 可以保证同一工厂生成的产品相互匹配,可以避免客户端和具体产品代码的耦合。
  3. 横向扩展简单:如果要新增一个系列的产品,只需增加一个工厂子类即可,不用修改原先的代码。例如我想在项目中添加一门Linux课程,只需要新建一个LinuxNote类,一个LinuxViideo类,和一个LinuxFactory类 并实现对应的接口即可,不用对之前的代码做任何修改。
抽象工厂模式的缺点:

​ 纵向扩展困难:如果要在一个产品系列中增加一个新的产品,就需要对工厂接口,及工厂子类的代码进行修改。例如:现在不仅要求老师提供录屏和笔记,还要提供家庭作业homework;这就需要在工厂接口Factory,以及他的所有子类中添加createHomework( )方法,违背了开闭原则。

你可能感兴趣的:(简单工厂模式,工厂方法模式,抽象工厂模式)