工厂模式

简单工厂

使用场景

工厂类负责创建的对象较少

客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不关心。

缺点

工厂类的职责过重,增加新的产品时需要修改工厂类的判断逻辑, 违背开闭原则。

不易于扩展过于复杂的产品结构。

工厂要创建的对象

public interface ICourse {
    void init();
    String getName();
}

public class JavaCourse implements ICourse {
    @Override
    public void init() {
        //do something
    }

    @Override
    public String getName() {
        return "Java";
    }
}

public class PythonCourse implements ICourse{
    @Override
    public void init() {
        //do something
    }

    @Override
    public String getName() {
        return "Python";
    }
}

工厂类

/**
 * 简单工厂, 不是23种设计模式之一
 */
@Slf4j
public class SimpleCourseFactory {

    /**
     * 根据名称判断要创建的对象(典型的简单工厂)
     * @param name
     * @return
     */
    public static ICourse createCourse(String name) {
        switch (name) {
            case "python":
                return new PythonCourse();
            case "java":
                return new JavaCourse();
            default:
                return null;
        }
    }

	// 根据全限定类名创建(升级的简单工厂)
    public static ICourse creatCourseByClassName(String className) {
        if (StringUtils.isBlank(className)) {
            throw new IllegalArgumentException("className name is required");
        }
        try {
            Class<?> aClass = Class.forName(className);
            if (!ICourse.class.isAssignableFrom(aClass)) {
                throw new IllegalArgumentException("class type wrong, not assignable from com.dreams.pattern.factory.simple.ICourse");
            }
            ICourse o = (ICourse) aClass.newInstance();
            o.init();
            return o;
        } catch (Exception e) {
            log.error("create instance for {}", className);
            log.error("create instance for {}", e);
            throw new IllegalArgumentException("can not create instance for className : " + className, e);
        }
    }

    //简化, clasz必须是ICourse的实现类
    public static ICourse createCourseByClasz(Class<? extends ICourse> clasz) {
        try {
            ICourse iCourse = clasz.newInstance();
            iCourse.init();
            return iCourse;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}

工厂方法模式

工厂方法模式是指定义一个创建对象的接口,但让实现类类决定实例化哪个类, 工厂方法让类的实例化推迟到子类中进行。

define an interface for creating an object, but let subclass decide witch class to instantiate.

The factory method lets a class defer instantiation it uses to subclasses.

适用场景

创建对象需要大量重复的代码

客户端不依赖产品类实例如何被创建、实现等细节

一个类通过其子类来指定创建哪个类。

image

产品

public interface ICourse {
    void init();
    String getName();
}

public class JavaCourse implements ICourse {
    @Override
    public void init() {
        //do something
    }

    @Override
    public String getName() {
        return "Java";
    }
}

public class PythonCourse implements ICourse{
    @Override
    public void init() {
        //do something
    }

    @Override
    public String getName() {
        return "Python";
    }
}

工厂

public interface ICourseFactory {
    ICourse create();
}

public class JavaCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        JavaCourse javaCourse = new JavaCourse();
        javaCourse.init();
        //do something
        return javaCourse;
    }
}

public class PythonCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        PythonCourse course = new PythonCourse();
        course.init();
        //do something
        return course;
    }
}

扩展产品&工厂

符合开闭原则

public class PhpCourse implements ICourse {
    @Override
    public void init() {
        //do something
    }

    @Override
    public String getName() {
        return "PHP";
    }
}

public class PhpCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        PhpCourse phpCourse = new PhpCourse();
        phpCourse.init();
        //do something
        return phpCourse;
    }
}

扩展产品&工厂

符合开闭原则

public class PhpCourse implements ICourse {
    @Override
    public void init() {
        //do something
    }

    @Override
    public String getName() {
        return "PHP";
    }
}

public class PhpCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        PhpCourse phpCourse = new PhpCourse();
        phpCourse.init();
        //do something
        return phpCourse;
    }
}

抽象工厂

提供一个创建一系列对象或相互依赖对象的接口,而无需指定它们具体的类。

考虑一门课程内容, 它包含视频内容和笔记, 对于不同的课程需要创建不同的视频内容和笔记。

2.png

后续可能的扩展

  • 增加新课程
  • 课程需要增加新内容,例如考试内容

CourseFactory.png

案例

Note

public interface INote {
    String getName();
    void createNote();
}
public class JavaNote implements INote{
    @Override
    public String getName() {
        return "Java Note";
    }

    @Override
    public void createNote() {
        System.out.println("记录Java笔记");
    }
}
public class PythonNote implements INote {
    @Override
    public String getName() {
        return "Python Note";
    }

    @Override
    public void createNote() {
        System.out.println("记录Python笔记");
    }
}

Video

public interface IVideo {
    void createVideo();
    String getName();
}
public class JavaVideo implements IVideo {

    @Override
    public void createVideo() {
        System.out.println("录制Java视频");
    }

    @Override
    public String getName() {
        return "Java Video";
    }
}
public class PythonVideo implements IVideo {

    @Override
    public void createVideo() {
        System.out.println("录制Python视频");
    }

    @Override
    public String getName() {
        return "Python Video";
    }
}

Factory

public interface CourseFactory {
    INote createNote();

    IVideo createVideo();
}
public class JavaCourseFactory implements CourseFactory {
    @Override
    public INote createNote() {
        JavaNote javaNote = new JavaNote();
        javaNote.createNote();
        return javaNote;
    }

    @Override
    public IVideo createVideo() {
        JavaVideo javaVideo = new JavaVideo();
        javaVideo.createVideo();
        return javaVideo;
    }
}
public class PythonCourseFactory implements CourseFactory {
    @Override
    public INote createNote() {
        PythonNote pythonNote = new PythonNote();
        pythonNote.createNote();
        return pythonNote;
    }

    @Override
    public IVideo createVideo() {
        PythonVideo pythonVideo = new PythonVideo();
        pythonVideo.createVideo();
        return pythonVideo;
    }
}

Test

Java course

    @Test
    public void testJavaCourse() {
        CourseFactory factory = new JavaCourseFactory(); //Java
        IVideo video = factory.createVideo();
        log.info("course.video : {}", video.getName());
        INote note = factory.createNote();
        log.info("course.note : {}", note.getName());
    }

录制Java视频
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.video : Java Video
记录Java笔记
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.note : Java Note

Python course

    @Test
    public void testPythonCourse() {
        CourseFactory factory = new PythonCourseFactory(); //Python
        IVideo video = factory.createVideo();
        log.info("course.video : {}", video.getName());
        INote note = factory.createNote();
        log.info("course.note : {}", note.getName());
    }

录制Python视频
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.video : Python Video
记录Python笔记
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.note : Python Note

参与者

  • 抽象工厂
  • 具体工厂
  • 抽象产品
  • 具体产品
  • 客户端

优缺点

  • 分类了具体的类
  • 易于更换产品系列
  • 有利于产品的一致性, 将一系列产品统一到一起创建。
  • 难以支持新种类产品(新增具体产品)
    • 新增产品需要新增抽象产品, 新增具体产品, 抽象工厂新增创建产品的接口, 所有已实现的具体工厂添加新产品的创建。

适用场景

客户端不依赖于产品类实例如何被创建、实现等细节。

强调一系列相关的产品对象一起使用,创建对象需要大量重复代码。

提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体的实现。

最佳实践

  • 将具体工厂作为单例
  • 创建产品, 抽象工厂只负责声明创建产品的接口, 真正产品的创建在具体工厂中实现
posted @   Dreamsrj  阅读(23)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示