设计模式学习总结(三)--工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

简单工厂模式

定义

简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

实例

需求:以学习课程为例

课程抽象类:

public interface ICourse {
    void learn();
}

Java 课程:

public class JavaCourse implements ICourse {
    @Override
    public void learn() {
        System.out.println("正在学习 Java ......");
    }
}

Mysql 课程:

public class MysqlCourse implements ICourse {
    @Override
    public void learn() {
        System.out.println("正在学习 Mysql ......");
    }
}

课程工厂类:

public class CourseFactory {

    public static final int COURSE_JAVA = 1;
    public static final int COURSE_MYSQL = 2;

    public ICourse getCourse(int courseType) {
        switch (courseType) {
            case COURSE_JAVA:
                return new JavaCourse();
            case COURSE_MYSQL:
                return new MysqlCourse();
            default:
                return null;
        }
    }
}

学习 Java 课程:

public static void main(String[] args) {
    CourseFactory factory = new CourseFactory();
    ICourse course = factory.getCourse(CourseFactory.COURSE_JAVA);
    course.learn();
}

优缺点

  • 优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。

  • 缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反 GRASPR 的高内聚的责任分配原则

工厂方法模式

定义

工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现 开-闭 原则,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。

在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

实例

以上面的课程为例,我们将工厂对象变为接口:

public interface ICourseFactory {

    ICourse getCourse();

}

实现两个课程各自的工厂:

public class JavaCourseFactory implements ICourseFactory {
    @Override
    public ICourse getCourse() {
        return new JavaCourse();
    }
}

public class MysqlCourseFactory implements ICourseFactory {
    @Override
    public ICourse getCourse() {
        return new MysqlCourse();
    }
}

测试类调用:

public static void main(String[] args) {
    ICourseFactory factory;
    // 学习 java
    factory = new JavaCourseFactory();
    ICourse javaCourse = factory.getCourse();
    javaCourse.learn();
    // 学习 Mysql
    factory = new MysqlCourseFactory();
    ICourse mysqlCourse = factory.getCourse();
    mysqlCourse.learn();
}

优缺点

优点:

  • 屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,只需关心产品的接口,只要接口保持不变,系统中的上层模块就不会发生变化。

  • 典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不需要关心,符合迪米特法则,符合依赖倒置原则,符合里氏替换原则。

  • 多态性:客户代码可以做到与特定应用无关,适用于任何实体类。

缺点:

  • 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到 DOM、反射等技术,增加了系统的实现难度。

抽象工厂模式

定义

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。

实例

针对一门课程除了学习外,我们应该还要有输出笔记操作,我们来实现下笔记对象。

增加笔记接口

public interface INote {

    void write();

    void read();

}

具体笔记实现:

public class JavaNote implements INote {
    @Override
    public void write() {
        System.out.println("写 Java 笔记");
    }

    @Override
    public void read() {
        System.out.println("读 Java 笔记");
    }
}

public class MysqlNote implements INote {
    @Override
    public void write() {
        System.out.println("写 Mysql 笔记");
    }

    @Override
    public void read() {
        System.out.println("读 Mysql 笔记");
    }
}

修改工厂接口:

public interface ICourseFactory {

    ICourse getCourse();

    INote getNote();
}

工厂实现:

public class JavaCourseFactory implements ICourseFactory {
    @Override
    public ICourse getCourse() {
        return new JavaCourse();
    }

    @Override
    public INote getNote() {
        return new JavaNote();
    }
}

public class MysqlCourseFactory implements ICourseFactory {
    @Override
    public ICourse getCourse() {
        return new MysqlCourse();
    }

    @Override
    public INote getNote() {
        return new MysqlNote();
    }
}

测试类:

public static void main(String[] args) {
    ICourseFactory factory;
    // 学习 java
    factory = new JavaCourseFactory();
    ICourse javaCourse = factory.getCourse();
    javaCourse.learn();
    INote javaNote = factory.getNote();
    javaNote.read();
    // 学习 Mysql
    factory = new MysqlCourseFactory();
    ICourse mysqlCourse = factory.getCourse();
    mysqlCourse.learn();
    INote mysqlNote = factory.getNote();
    mysqlNote.read();
}

优缺点

优点:

抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

缺点:

产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

原文地址:https://www.cnblogs.com/markLogZhu/p/11453099.html