本设计模式资料源于慕课网,讲师:Geely 《Java设计模式精讲 Debug方式+内存分析》,本人作为自己手打整理作为学习的归纳总结。
一,简单工厂
1,定义和介绍
- 定义:由一个工厂对象决定创建出哪一种产品类的实例
- 类型:创建型,但不属于 GOF 23种设计模式
2,适用场景
- 工厂类负责创建的对象较少
- 客户对象(应用层)只关心传入工厂类的参数,对于如何创建对象(逻辑)不关心
3,优点
- 只需要传入一个正确的参数,就可以获取到你所需要的对象,而无需要知道其创建细节
4,缺点
- 工厂类的职责相对过重,增加新的产品,需要修改工厂类的判断逻辑,违背开闭原则
5,代码演示
- 业务场景
返回不同课程的视频
这里是定义了课程行为的 Course 类的,这个类里面定义了 getVideo() ,表明了要继承这个抽象类的所有课程都必须要有生产视频的这个方法。然后我们分别定义了 JavaCourse 和 PythonCourse 两个类对这个类进行继承。
package com.try1.design.creational.simplefactory;
public abstract class Course {
public abstract void getVideo();
}
package com.try1.design.creational.simplefactory;
public class JavaCourse extends Course{
public void getVideo(){
System.out.println("录制java课程!");
}
}
package com.try1.design.creational.simplefactory;
public class PythonCourse extends Course {
@Override
public void getVideo() {
System.out.println("录制python课程!");
}
}
package com.try1.design.creational.simplefactory;
public class CourseFactory {
public Course createCourse(Class c){
Course course=null;
try {
course=(Course)Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return course;
}
}
package com.try1.design.creational.simplefactory;
public class Test {
public static void main(String[] args) {
CourseFactory courseFactory=new CourseFactory();
Course course=courseFactory.createCourse(JavaCourse.class);
if(course==null){
return ;
}
course.getVideo();
}
}
- 小结
简单工厂简单来看就是,定义一个课程抽象类,用不同的具体课程来继承,再定义一个能返回所需继承类的工厂类。
测试中则用到了反射的机制。
二,工厂方法
1,定义和类型
- 定义:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行
- 类型:创建型
2,适用场景
- 创建对象需要大量重复的代码
- 客户端(应用层)不依赖于产品类实例如何被创建,实现等细节
- 一个类通过其子类来指定创建哪个对象
3,优点
- 用户只需要关心所需产品对应的工厂,无需关心创建细节
- 加入新产品符合开闭原则,提高可扩展性。
4,缺点
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
5,代码演示
- 业务场景
现在若干课程,每种课程有相对应的视频
对于简单工厂模式,可以通过两个底层的抽象类来理解。
首先同样定义了抽象类,规定课程的功能。
package com.try1.design.creational.factorymethod;
public abstract class Course {
public abstract void getVideo();
}
package com.try1.design.creational.factorymethod;
public class JavaCourse extends Course {
public void getVideo(){
System.out.println("录制java课程!");
}
}
package com.try1.design.creational.factorymethod;
public class PythonCourse extends Course {
@Override
public void getVideo() {
System.out.println("录制python课程!");
}
}
然后我们定义了另外一个 CourseFactory 抽象类,这个类用做返回具体的 Course 继承类,返回值是设置成 Course。再来同样是用 JavaCourseFactory 和 PythonCourseFactory 两个类对这个类继承,这样我们可以绑定返回具体指定的 Course。
package com.try1.design.creational.factorymethod;
public abstract class CourseFactory {
public abstract Course createCourse();
}
package com.try1.design.creational.factorymethod;
public class JavaCourseFactory extends CourseFactory {
@Override
public Course createCourse() {
return new JavaCourse();
}
}
package com.try1.design.creational.factorymethod;
public class PythonCourseFactory extends CourseFactory {
@Override
public Course createCourse() {
return new PythonCourse();
}
}
最后是我们最外层的调用,我们只需要用一个 CourseFactory 来接相应的工厂,然后用这个生成的工厂类,得到想要的Course继承类,然后直接调用这个对应继承类的创建视频方法。
package com.try1.design.creational.factorymethod;
/**
* 抽象工厂模式,分别制造不同的类和继承不同的方法
*/
public class Test {
public static void main(String[] args) {
// CourseFactory courseFactory=new CourseFactory();
// Course course=courseFactory.createCourse(JavaCourse.class);
// if(course==null){
// return ;
// }
// course.getVideo();
CourseFactory courseFactory=new JavaCourseFactory();
Course course=courseFactory.createCourse();
course.getVideo();
CourseFactory courseFactory2=new PythonCourseFactory();
Course course2=courseFactory2.createCourse();
course2.getVideo();
}
}
- 小结
总的来说我们是只传了一个工厂是哪一个这个参数,然后我们就能得到,最后的课程视频。符合迪米特法则
简单来说,工厂抽象类只返回具体的功能类这一个功能。而这些具体功能类则是要继承一个决定他们共有功能的抽象类。
三,抽象工厂
1,定义和介绍
- 定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口
无须指定它们具体的类 - 类型:创建型
2,适用场景
- 客户端(应用端)不依赖于产品类实例如何被创建,实现等细节
- 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现
3,优点
- 具体产品在应用层代码隔离,无需关心其创建细节
- 将一个系列的产品族统一到一起进行创建
4,缺点
- 规定了所有的可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
- 增加了系统的抽象性和理解难度
package com.try1.design.creational.abstractfactory;
public abstract class Article {
public abstract void produce();
public void so(){
System.out.println("!!");
}
}
package com.try1.design.creational.abstractfactory;
public class JavaArticle extends Article {
@Override
public void produce() {
System.out.println("生成java笔记!");
}
}
package com.try1.design.creational.abstractfactory;
public class PythonArticle extends Article {
@Override
public void produce() {
System.out.println("生成Python笔记!");
}
}
package com.try1.design.creational.abstractfactory;
public abstract class Video {
public abstract void produce();
}
package com.try1.design.creational.abstractfactory;
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制java视频!");
}
}
package com.try1.design.creational.abstractfactory;
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制python视频!");
}
}
package com.try1.design.creational.abstractfactory;
public interface CourseFactory {
public Video getVideo();
public Article getAticle();
}
package com.try1.design.creational.abstractfactory;
public class JavaCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
@Override
public Article getAticle() {
return new JavaArticle();
}
}
package com.try1.design.creational.abstractfactory;
public class PythonCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
@Override
public Article getAticle() {
return new PythonArticle();
}
}
package com.try1.design.creational.abstractfactory;
public class Test {
public static void main(String[] args) {
CourseFactory courseFactory=new JavaCourseFactory();
Article article=courseFactory.getAticle();
article.produce();
// article.so();
Video video=courseFactory.getVideo();
video.produce();
}
}
- 小结
这里是把课程的功能行为在工厂抽象类里面定义,继承了对应工厂抽象类,则需要返回对应的功能实现类,功能实现类,同样是继承了对应的功能抽象类。
这样的写法是面对一个产品族的功能来的,这样方便与对于一个产品的所有功能进行执行获取,之前的写法则是对于得到对应的某一个类来的。这样写优劣都在于功能的管理上,优点在于统一整理,缺点在于不利于增加;
四,总结
工厂模式是 Java 封装的一个重要体现,这种设计模式的特点就在于,我们只需要知道我们要哪一个对象,就能获取到这个对象的所有被封装好的功能,或是一个个体。
如果要按照功能抽象,就用抽象工厂模式的写法,如果是按照个体抽象,就用工厂方法的写法