设计模式之简单工厂、工厂方法模式、抽象工厂模式解析

设计模式之工厂模式解析

文章目录

  • 设计模式之工厂模式解析
  • 一、简单工厂模式
    • 什么是简单工厂模式
    • 示例
  • 二、工厂方法模式
    • 什么是工厂方法模式
    • 示例
  • 三、抽象工厂模式
    • 什么是抽象工厂模式
    • 示例

一、简单工厂模式

  • 什么是简单工厂模式

    简单工厂模式(Simple Factory Pattern) 是指由一个工厂对象决定创建出哪一种产品类的实例,它不属于GOF23种设计模式。简单工厂模式适用于工厂类负责创建对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心。来看下简单工厂模式的类图:
    设计模式之简单工厂、工厂方法模式、抽象工厂模式解析_第1张图片

  • 示例

    创建一个标准的课程接口类

    public interface ICourse {
        //录制视频
        void record();
    }
    

    创建一个Java课程的实现类JavaCourse

    public class JavaCourse implements ICourse {
    
    	@Override
        public void record() {
            System.out.println("录制Java课程");
        }
    }
    

    再创建一个Python课程的实现类PythonCourse

    public class PythonCourse implements ICourse {
    
    	@Override
        public void record() {
            System.out.println("录制Python课程");
        }
    }
    

    创建Course课程工厂类

    /**
     * 简单工厂模式
     *      隐藏课程创建的细节,客户端只需要知晓调用参数即可,方便了客户端的使用
    
     * @author zdp
     * @date 2023/9/2 17:53
     */
    @Slf4j
    public class CourseSimpleFactory {
    
        /**
         * 课程简单工厂 V1
         *    缺点:
         *        如果业务继续扩展,要增加其他课程,那么工厂中的create()方法需要根据产品链的丰富来修改代码逻辑
         *        不符合开闭原则,因此,可以对简单工厂继续优化 {@link CourseSimpleFactory#createV2(java.lang.Class)}
         * @author zdp
         * @date   2023/9/2 17:54
         * @return ICourse
         */
        public static ICourse createV1(String courseName) {
            if (JAVA.equals(courseName)) {
                return new JavaCourse();
            } else if (PYTHON.equals(courseName)) {
                return new PythonCourse();
            }
            throw new RuntimeException("un support courseName: " + courseName);
        }
    
        /**
         * 课程简单工厂 V2
         *      优化后,即使业务继续扩展,工厂类也不需要再次修改了
         * @author zdp
         * @date   2023/9/2 17:54
         * @return ICourse
         */
        public static ICourse createV2(Class<? extends ICourse> clazz) {
            try {
                Assert.notNull(clazz, "CourseFactory create ICourse clazz must not null!");
                return clazz.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                log.error("工厂类创建异常! exception: {}", e.getMessage());
                throw new RuntimeException(e);
            }
        }
    }
    

    简单工厂模式测试

    /**
     * 使用简单工厂模式来创建课程,
     *     简单工厂模式在JDK源码中也使用到了, 如Calendar类的 Calendar.getInstance();
     *     其他如: Logback中也使用到了, LoggerFactory.getLogger();
     *
     *  简单工厂模式也存在它的缺点:
     *      工厂类的职责相对过重,不易于扩展过于复杂的产品结构
     * @author zdp
     * @date 2023/9/2 17:38
     */
    public class SimpleFactoryTest {
    
        public static void main(String[] args) {
            // 简单工厂
            ICourse java = CourseSimpleFactory.createV1(JAVA);
            java.record();
    
            // 优化后的简单工厂 兼容性更强
            ICourse javaCourse = CourseSimpleFactory.createV2(JavaCourse.class);
            javaCourse.record();
    
            ICourse pythonCourse = CourseSimpleFactory.createV2(PythonCourse.class);
            pythonCourse.record();
        }
    }
    
    • 优点
      • 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,可以根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
      • 客户端只需要传入一个正确的参数,就可以获取所需要的对象,无须知道其创建的细节。
    • 缺点
      • 工厂类的职责相对过重,增加新的产品时需要修改工厂类的判断逻辑,违背开闭原则。
      • 不易于扩展过于复杂的产品结构。

二、工厂方法模式

  • 什么是工厂方法模式

    工厂方法模式(Factory Method Pattern) 是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入的产品符合开闭原则。
    工厂方法模式 主要解决产品扩展大问题,在简单工厂中,随着产品链的丰富,如果每个课程的创建逻辑有区别的话,工厂的职责会变得越来越多,不便于维护。根据单一职责我们继续拆分,Java课程由Java工厂创建,Python课程由Python工厂创建,对工厂本身也做一个抽象。来看下工厂方法模式的类图:
    设计模式之简单工厂、工厂方法模式、抽象工厂模式解析_第2张图片

  • 示例

    ICourse 、JavaCourse、PythonCourse类同简单工程模式
    再创建一个ICourseFactory工厂接口类

    public interface ICourseFactory {
        ICourse create();
    }
    

    分别创建Java课程、Python课程的工厂类JavaCourseFactory、PythonCourseFactory

    public class JavaCourseFactory implements ICourseFactory {
        public ICourse create() {
            return new JavaCourse();
        }
    }
    
    public class PythonCourseFactory implements ICourseFactory {
        public ICourse create() {
            return new PythonCourse();
        }
    }
    

    工厂方法模式测试

    public class FactoryMethodTest {
        public static void main(String[] args) {
            ICourseFactory factory = new PythonCourseFactory();
            ICourse course = factory.create();
            course.record();
            factory = new JavaCourseFactory();
            course = factory.create();
            course.record();
        }
    }
    
    • 优点
      • 用户只需关心所需产品对应的工厂,无须关心创建细节。
      • 加入新产品符合开闭原则,提高了系统的可扩展性。
    • 缺点
      • 工厂方法模式中类的个数容易过多,增加系统复杂度
      • 增加了系统的抽象性和理解难度

三、抽象工厂模式

  • 什么是抽象工厂模式

    抽象工厂模式 (Abastract Factory Pattern) 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。工厂方法模式在增加一个具体产品的时候,都要增加对应的工厂。 但是抽象工厂模式只有在新增一个产品族时才需要新增工厂。 也就是说,工厂方法模式的一个工厂只能创建一个具体产品。而抽象工厂模式的一个工厂可以创建属于一类类型的多种具体产品。工厂创建产品的个数介于简单工厂模式和工厂方法模式之间。
    我的话来理解抽象工厂模式和工厂方法模式

    • 抽象工厂模式
      • 当新增一个产品族的时候才会增加一个工厂
    • 工厂方法模式
      • 当新增一个具体产品的时候就会增加一个工厂

    就类比生活中的例子来举例,美的、格力、海尔三大厂商会生产不同的电器

    美的 洗衣机 空调 热水器
    格力 洗衣机 空调 热水器
    海尔 洗衣机 空调 热水器

    横向就是一个产品族,纵向就是产品的等级结构,抽象工厂模式的工厂就是以产品族为维度来创建的,现在针对上面的课程优化,不仅是单独的课程内容,现在又新增了录播Video、Note功能,按照上面关系映射到本次需求内容中关系如下:

    Java 课程信息course 录播videl 笔记note
    Python 课程信息course 录播videl 笔记note
    GO 课程信息course 录播videl 笔记note

    现在关系理清楚了再来看下类图:
    设计模式之简单工厂、工厂方法模式、抽象工厂模式解析_第3张图片

  • 示例

    基于上面的课程再添加一个录播视频和提供笔记的功能,以上的课程不再是单独提供课程信息,还要包含录播视频和笔记才算是完整的课程。分别创建一个IVideo和INote的接口

    public interface IVideo {
        //录播视频
        void video();
    }
    
    public interface INote {
    	//课堂笔记
        void note();
    }
    

    创建一个课程的抽象工厂类

    public abstract class AbstractCourseFactory {
    
        public abstract ICourse createCourse();
    
        public abstract IVideo createVideo();
    
        public abstract INote createNote();
    }
    

    接下来创建Java产品族,Java视频JavaVideo类、Java笔记JavaNote类

    public class JavaVideo implements IVideo {
        public void video() {
            System.out.println("Java 录播");
        }
    }
    
    public class JavaNote implements INote {
        public void note() {
            System.out.println("Java 笔记");
        }
    }
    

    创建Java产品族的具体工厂JavaFactory

    public class JavaFactory extends AbstractCourseFactory {
    
        @Override
        public ICourse createCourse() {
            return new JavaCourse();
        }
    
        @Override
        public IVideo createVideo() {
            return new JavaVideo();
        }
    
        @Override
        public INote createNote() {
            return new JavaNote();
        }
    }
    

    接下来创建Python产品族,Python视频PythonVideo类、Python笔记PythonNote类

    public class PythonVideo implements IVideo {
        public void record() {
            System.out.println("Python 录播");
        }
    }
    
    public class PythonNote implements INote {
        public void edit() {
            System.out.println("Python 笔记");
        }
    }
    

    创建Python产品族的具体工厂PythonFactory

    public class PythonFactory extends AbstractCourseFactory {
    
        @Override
        public ICourse createCourse() {
            return new PythonCourse();
        }
    
        @Override
        public IVideo createVideo() {
            return new PythonVideo();
        }
    
        @Override
        public INote createNote() {
            return new PythonNote();
        }
    }
    
    

    抽象工厂模式测试

    public class AbstractFactoryTest {
    
        public static void main(String[] args) {
            // Java一系列课程 由一个工厂实现
            AbstractCourseFactory javaFactory = new JavaFactory();
    
            ICourse javaCourse = javaFactory.createCourse();
            javaCourse.record();
    
            IVideo javaVideo = javaFactory.createVideo();
            javaVideo.video();
    
            INote javaNote = javaFactory.createNote();
            javaNote.note();
        }
    }
    

    上面的代码完整的描述了两个产品族Java课程和Python课程,也描述了两个产品等级视频和笔记。抽象工厂非常完美清晰的描述了这样一层复杂的关系。

    • 优点
      • 抽象工厂模式隔离了具体类的生产,使得客户并不需要知道什么被创建
      • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象
      • 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”
    • 缺点
      • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
      • 增加了系统的抽象性和理解难度

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