说在前面
不用设计模式并非不可以,但是用好设计模式能帮助我们更好地解决实际问题,设计模式最重要的目的是为了解耦。设计模式其实我们天天都在用,但自己却无明显感知。所以学习设计模式也是锻炼将业务需求转换为技术实现的一种非常有效的方式。
简单工厂模式
指一个工厂对象决定创建出某种产品的实例,将这一过程封装起来对用户不可见,这种形式称之为工厂模式。比如日常生活中你需要买东西,商家给你提供你需要的东西,你买来直接使用就好了,商家的生产过程对你来说不可见。
简单工厂模式的优点:减少代码的重复编写,使代码更容易复用。
通常我们所说的工厂模式是指工厂方法模式,它也是使用频率最高的工厂模式,属于创建型模式,不属于23种设计模式之一。在简单工厂模式中,客户端通过工厂类来创建一个产品类的实例,而无须直接使用new关键字来创建对象,它是工厂模式家族中最简单的一员。
适用的场景
- 简单工厂类负责创建对象较少
- 客户端只需要传入工厂类所需的参数,对其如何创建实例的过程不需要关心(传参,对内部实现不关心)
简单工厂模式的优点:只需传入一个正确的参数,就可以获取所需对象,无须知道实现细节
简单工厂模式的缺点
- 将多个参数的创建放到一个类中(因为需要根据不同的参数,创建不同的实例),所以职责过重,当新增参数时,都需要去修改其内部逻辑,违背了开闭原则
- 不利于扩展相对复杂的结构
/**
* 抽象产品类
* 需求:创建不同学科
* 只生成一个课程接口,都可以实现它,创建不同的课程:语数外政史地理化生等
*/
public interface ICourse {
void createCourse();
}
/**
* 具体产品类
* 实现课程接口,指定具体为Java学科
* @description java学科
* @date 2019/4/9 11:36
*/
public class JavaCourse implements ICourse {
@Override
public void createCourse() {
System.out.print("java课程开始------");
}
}
/**
* 课程测试类,学习Java课程
* @description
* @date 2019/4/9 11:37
*/
public class CourseTest {
public static void main(String[] args) {
//这种写法,当定义多种学科的时候,需要new多次实例,比较臃肿繁琐,这里可以使用工厂
//可以将对象的创建交给工厂处理,而不是自己创建
ICourse course = new JavaCourse();
course.createCourse();
}
}
/**
* 具体产品工厂类
* 新增一个工厂类,用于创建不同的学科,统一由自己创建对象
* @description 课程大纲工厂类
* @date 2019/4/9 11:39
*/
public class CourseFactory {
public ICourse create(String name) {
if ("java".equals(name)) {
return new JavaCourse();
} else {
return null;
}
}
}
/**
* 用于测试工厂类,创建不同的学科
* @description
* @date 2019/4/9 11:37
*/
public class CourseTest {
public static void main(String[] args) {
//使用工厂来创建不同的学科,只需要new一次工厂即可,不需要多次new
CourseFactory factory = new CourseFactory();
//根据需求,创建不同的学科
ICourse course = factory.create("java");
course.createCourse();
}
}
//但是上面这种方式也不够好,当随便传入参数的时候就会返回null
//改为类创建
public class CourseFactory {
public ICourse create(Class clz) {
try {
if (clz != null) {
return (ICourse) clz.newInstance();
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
//测试
public class CourseTest {
public static void main(String[] args) {
CourseFactory factory = new CourseFactory();
ICourse course = factory.create(JavaCourse.class);
course.createCourse();
}
}
上述涉及的ICourse、JavaCourse、CourseFactory、CourseTest类看似很多,比较繁杂,其实可以这么理解,ICourse相当于某个产品的构想,比如一个笔记本的组成,由CPU、内存、硬盘等硬件组成,而JavaCourse就相当于是具体的某样硬件,而CourseFactory就相当是代工厂,将具体的硬件生产出来,CourseTest就类似于消费者,不需要知道你是怎么生产的,给我就行
jdk中的Calendar类和slf4j中的LoggerFactory类就是简单工厂的案例
而Calendar类和LoggerFactory类又都是单例模式,所以可以印证,工厂模式和单例模式又是非常的紧密的,都是有所关联的。
工厂方法模式
是指定义一个创建对象的工厂接口,但让实现这个接口的类来决定实例化某个具体的类,工厂方法让类的实例化推迟到实现类中进行。
适用场景
- 创建对象需要大量重复的代码。
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
- 一个类通过其子类来指定创建哪个对象
与简单工厂的区别
- 简单工厂:创建对象的操作在工厂中进行,根据传入的不同参数来创建不同的对象
- 工厂方法:工厂中只定义创建对象的接口定义,将对象的创建交给实现类中进行
简单工厂内有许多的if-else判断,当新的参数进来时,需要进行修改,违背了开闭原则,不利于代码维护,而工厂方法模式,将不同的对象由不同的工厂来创建,交由不同的实现类来进行实例化
/**
* 该类只定义,不去创建对象
* @author wcj
* @description
* @date 2019/8/15 15:42
*/
public interface ICourseFactory {
//返回一个课程大纲
ICourse create();
}
/**
* 由实现类进行来实例化所需要的类,单一职责原则,只创建Java的,如果有别的课程,则再创建一个实现类实现ICourseFactory,
* 实例化对应的对象
* @author wcj
* @description
* @date 2019/8/15 15:43
*/
public class JavaCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
//返回具体学科的课程大纲
return new JavaCourse();
}
}
工厂方法模式的优点:
- 对于用户而言,只需关心所需产品对应的工厂,无须关心创建细节
- 加入新产品符合开闭原则,提高了系统的可扩展性
工厂方法模式的缺点:
- 类的个数越来越多,增加了代码结构的复杂度
- 增加了系统的抽象性和理解难度