简单工厂、工厂方法、抽象工厂、单例模式
一、设计模式总览
1.开闭原则:对扩展开放,对修改关闭
2.单一职责原则:一个类、接口、方法只做一件事
3.依赖倒置原则:通过抽象使个各类,模块相互之间不影响,实现松耦合,尽量面向抽象,接口编程
4.接口隔离原则: 面向抽象基础上,一个接口只做某一类事情,客户端不应该依赖不同的端口
5.迪米特法则:最少知道原则,一个类对他所依赖的类知道的越少越好
6.里氏替换原则:子类可以扩展父类的功能,但不能修改父类已有的功能,避免继承泛滥
7.合成复用原则:尽量使用对象组合、聚合而尽量不适用继承
说明:
没有设计模式,我们的代码也可以运行,那我们为什么要学习设计模式呢?
设计模式对我们的代码逻辑并没有影响,但是利用设计模式可以让我们的代码变得更易读、更清晰、更优雅的代码,这一点很重要
二、Simple Factory Pattern简单工厂模式
1、简单工厂模式定义
简单工厂模式(Simple Factory Pattern)是指由一个工程对象决定创建出哪一种产品类的实例。
属于创建型模式,但它不属于GOF 23种设计模式。
我们来举例说明:
MyCourse接口(定义了一个record()方法):
package org.example.pattren.factory.simplefactory;
public interface MyCourse {
void record();
}
JavaCourse类和PythonCourse类:实现了MyCourse接口
public class JavaCourse implements MyCourse {
@Override
public void record() {
System.out.println("录制Java课程");
}
}
public class PythonCourse implements MyCourse {
@Override
public void record() {
System.out.println("录制Python课程");
}
}
以上准备结束后,正常状况下我们通常会分别new一个对象来使用,
package org.example.pattren.factory.simplefactory;
public class Test {
public static void main(String[] args) {
MyCourse javaCourse = new JavaCourse();
MyCourse pythonCourse = new PythonCourse();
javaCourse.record();
pythonCourse.record();
}
}
这样使用显得比较繁琐,而且每用一个项目都需要new一个对象,但利用简单工厂模式我们可以忽略创建对象的逻辑,只需要传递一个正确的参数就可以生产需要的对象。下面我们创建一个工厂类:
public class CourseFactory {
public MyCourse create(String name){
if("Java".equals(name)){
return new JavaCourse();
} else if("Python".equals(name)){
return new PythonCourse();
} else{
return null;
}
}
}
这样也实现了一个工厂类的基本功能,只要你传入对应的参数,就可以获得对应对象。但如果我们传入的参数有错误或并没有这个类这个只会返回null,并不会报错,因此这个工厂类还可以进行优化。
优化后的工厂类CourseFactory
package org.example.pattren.factory.simplefactory;
public class CourseFactory {
public MyCourse create(String className){
if(!(null == className || "".equals(className))){
try {
return (MyCourse)Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
上面优化后,利用了Java重要的技术:反射,并且加入异常处理,但这样的话,我们在调用函数是需要传入类的全路径,容易打错还很麻烦。。。我们就可以进一步优化工厂类,如下:
public class CourseFactory {
public MyCourse create(Class<? extends MyCourse> clazz){
if(null != clazz){
try {
return (MyCourse)clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
我们直接传入一个类,并且利用泛型通配符限制传入的参数必须是MyCourse及其子类(<? extends MyCourse>上线为MyCourse),同时有异常处理这样就比较完善,测试类中只需要传入想生产的类即可。
package org.example.pattren.factory.simplefactory;
import java.util.Calendar;
public class Test {
public static void main(String[] args) {
MyCourse course = new CourseFactory().create(JavaCourse.class); // 只需要传入对应的class即可
course.record();
Calendar.getInstance(); //Calendar也利用了工厂类
}
}
Calender类
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
2、简单工厂使用场景
工厂类负责创建的对象较少。
客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心
3、简单工厂的优点
只需传入一个正确的参数,就可以获取你所需要的对象无须知道其创建的细节
4、简单工厂的缺点
工厂类的职责相对过重,增加新的产品时需要修改工厂类的判断逻辑,违背开闭原则。
不易于扩展过于复杂的产品结构。
三、Factory Method Pattern工厂方法模式
1、工厂方法模式定义
工厂方法模式(Factory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类进行
属于创建型设计模式
工厂方法接口相比于简单工厂模式新添加了一个MyCourseFactory接口,接口内仅仅声明了一个create()方法用来创建一个MyCourse
public interface MyCourseFactory {
MyCourse create();
}
同时定义JavaCourseFactory和PythonCourseFactory类,实现MyCourseFactory(工厂接口),将功能划分下去
public class JavaCourseFactory implements MyCourseFactory{
@Override
public MyCourse create() {
return new JavaCourse();
}
}
public class PythonCourseFactory implements MyCourseFactory{
@Override
public MyCourse create() {
return new PythonCourse();
}
}
上面两个类中的JavaCourse类和PythonCourse类就是讲解简单工厂时使用的类,这里不再展示
接下来我们演示一下工厂方法模式
public class Test {
public static void main(String[] args) {
MyCourseFactory factory = new PythonCourseFactory();
MyCourse course = factory.create();
course.record();
}
}
工厂方法模式在实例化对象时只需要new对应的工厂类,并调用create()方法来创建对象
2、工厂方法模式适用场景
对象创建需要大量重复的代码。
客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
一个类通过其子类来制定创建哪个对象
3、工厂方法模式的优缺点
优点
用户只需关心所需产品对应的工厂,无需关心创建细节。
加入新产品符合开闭原则,提高了系统的可扩展性。
缺点
类的个数容易过多,增加了代码结构的复杂度。
增加了系统的抽象性和理解难度
四、Abstarct Factory Pattern抽象工厂模式
1、抽象工厂模式的定义和使用
定义:抽象工厂模式是指提供一个创建一系列相关或互相依赖对象的接口,无需指定他们具体的类。
属于创建型设计模型。
我们还是用前面课程的例子,课程不应该只有录播,还应该提供笔记之类的功能,这里为教学演示不太复杂,我们只涉及录播和笔记。
我们将MyCourse接口的功能分开为MyVideo和MyNote
public interface MyVideo {
void record(); //录播
}
public interface MyNote {
void edit(); //编辑
}
我们还需要一个课程工厂CourseFactory,这个工厂既可以interface也可以用abstract类修饰,这里如何选择呢?
如果工厂没有通用逻辑的话一般用interface(接口)修饰即可
工厂有通用逻辑就使用abstract(抽象类)修饰