概述
尝试理解以下概念,有助于学习工厂模式。
产品族:一个或多个具有相同特征关联产品的集合。
简单工厂 一个总工厂,可以生产任意产品族的产品。
工厂方法 :将总工厂进行细分,不同类型工厂,生产其对应产品族的一个类型产品。
抽象工厂:不同类型的工厂,生产其对应产品族的多个类型产品。
简单工厂模式
注意:简单工厂模式不属于GoF设计模式
定义:工厂根据传入的参数即可返回客户所需的对象,客户而不需要知道具体类的类名字。客户端只需传入相应的参数,就可以得到相应的对象实例,并不关心工厂是如何进行创建实现的。
适用:仅仅适用于工厂负责创建对象较少的情况下
优点:
- 实现了对责任的分割,它提供了专门的工厂类用于创建对象
- 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可
缺点:
- 工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
实例说明:
通过CourseFactory,来通过传入参数创建并返回对应的课程实例。
ICouse为课程接口,所有课程都得实现这个接口。
模式结构和其设计图如下:
工厂角色:CourseFactory
抽象产品:ICourse
具体产品:JavaCourese、PythonCourse
代码:
ICourse
public interface ICourse {
void record();
}
JavaCourese
public class JavaCourse implements ICourse {
@Override
public void record(){
System.out.println("Java课程");
}
}
PythonCourse
public class PythonCourse implements ICourse {
@Override
public void record() {
System.out.println("Python 课程");
}
}
CourseFactory
public class CourseFactory {
//缺点:业务拓展的话 不能满足开闭原则 如果增加课程就得对源代码进行else if 修改。
//修改源代码 不可取
public ICourse create1(String name)
{
if(name.equals("Java"))
{
return new JavaCourse();
}
else if(name.equals("Python"))
{
return new PythonCourse();
}
else
return null;
}
//优点:通过反射机制 动态灵活性好
//缺点:参数为字符串可控性不好 继续优化
public ICourse create2(String classname)
{
if(!(classname==null||classname.equals("")))
{
try {
return (ICourse)Class.forName(classname).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
//参数采用泛型 为上界限通配符 所有继承接口ICounse的类或接口均可作为参数
public ICourse create(Class<? extends ICourse> c)
{
if(c!=null)
{
try {
return c.newInstance();
}
catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
SimpleFactoryTest
public class SimpleFactoryTest{
public static void main(String[] args) {
CourseFactory factory=new CourseFactory();
//创建Java课程
factory.create(JavaCourse.class).record();
factory.create(PythonCourse.class).record();
factory.create(WebCourse.class).record();
}
}
工厂方法模式
定义:属于类创建型模式。此模式中,将工厂职责进行细分。工厂父类负责定义创建产品对象的公共接口,工厂子类负责实现接口生产具体的物品。工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。实现开闭原则和单一职责。
使用情况:
- 客户类不需要知道具体产品类的类名,只需要知道所对应的工厂即可。
- 一个类通过其子类来指定创建哪个对象,抽象工厂类提供创建产品的接口,子类具体实现。
优点:
- 封装了产品对象具体的创建细节。
- 符合开闭原则,具有良好的扩展性。添加新的产品族时,只需要加一个具体工厂和具体产品就行。
- 符合单一职责。
缺点:
添加新产品时,需要编写新的具体产品类和与之对应的工厂类。增加了系统的复杂度,有了更多的类需要编译和运行,给系统带来了额外的开销。
举例说明:
将CourseFactory职责细分,创建ICourseFactory父接口。
具体实现则是,PythonCourseFactory和JavaCourseFactory两个类,分别负责创建Python和Java课程。
模式结构和其结构图:
- 抽象工厂:ICourseFactory
- 具体工厂: JavaCourseFactory 、PythonCourseFactory
- 抽象产品:ICourse
- 具体产品: JavaCourese、PythonCourse
代码:
ICourseFactory
public interface ICourseFactory {
ICourse create();
}
不同的工厂根据自身的职责不同,分别实现父接口的方法,创建出不同的对象
JavaCourseFactory
public class JavaCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
return new JavaCourse();
}
}
PythonCourseFactory
public class PythonCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new PythonCourse();
}
}
Test
public class Test {
public static void main(String[] args) {
ICourseFactory javaCourseFactory=new JavaCourseFactory();
javaCourseFactory.create().record();
ICourseFactory pythonCourseFactory=new PythonCourseFactory();
pythonCourseFactory.create().record();
}
}
抽象工厂模式
定义:抽象工厂模式是工厂方法模式的泛化版本,工厂方法模式是一种特殊的抽象工厂模式。工厂方法模式中,工厂只生产该类型的一个产品,而在抽象工厂模式中,工厂具有了该类型的多个产品功能。
优点:
- 所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需改变具体工厂的创建实例,就可以在某种程度上改变整个软件系统的行为。抽象工厂模式实现了高内聚,低耦合的目的。
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族的对象。
- 增加新的具体工厂和产品族方便,无须修改已有代码,符合开闭原则。
缺点:产品族内部产品的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,这时候抽象工厂需要修改,则几乎所有的具体工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
适用情况:
- 系统不依赖产品类实例如何被创建、组合和表达的细节。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。java和python是两个产品族。
- 属于同一产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。video和note属于一个产品族。
举例说明:本例中对于每个工厂的职责从一个变成了多个职责,Java工厂由最初的生产Java课程变成了生产Java笔记和Java录像多个工作。一个产品族包含了多个产品。
模式结构和图:
- 抽象工厂:ICourseFactory
- 具体工厂:JavaCourseFactory 、PythonCourseFactory
- 抽象产品:INote、IVideo
- 具体产品:JavaNote、JavaVideo、PythonNote、PythonVideo
代码:
ICourseFactory
public interface ICourseFactory {
IVideo createVideo();
INote createNote();
}
JavaCourseFactory
public class JavaCourseFactory implements ICourseFactory {
@Override
public IVideo createVideo() {
return new JavaVideo();
}
@Override
public INote createNote() {
return new JavaNote();
}
}
PythonCourseFactory
public class PythonCourseFactory implements ICourseFactory {
@Override
public IVideo createVideo() {
return new PythonVideo();
}
@Override
public INote createNote() {
return new PythonNote();
}
}
INote
public interface INote {
void record();
}
JavaNote
public class JavaNote implements INote {
@Override
public void record() {
System.out.println("Java 笔记");
}
}
PythonNote
public class PythonNote implements INote {
@Override
public void record() {
System.out.println("Python 笔记");
}
}
IVideo
public interface IVideo {
void record();
}
JavaVideo
public class JavaVideo implements IVideo {
@Override
public void record() {
System.out.println("Java video");
}
}
PythonVideo
public class PythonVideo implements IVideo {
@Override
public void record() {
System.out.println("Python video");
}
}