学习路径:https://coding.imooc.com/class/270.html
概念区别
【简单工厂】不属于设计模式,是一种【编码风格】
【工厂方法】、【抽象工厂】属于【创建型】的设计模式
应用场景
1. 简单工厂
// 基础简单工厂
FruitFactory fruitFactory = new FruitFactory();
// 约定一个标识让工厂去生成,这里可以用反射的方式演进得更合理
Fruit fruit = fruitFactory.getFurit("apple");
fruit.produce();
// 使用反射演进的简单工厂
FruitFactory fruitFactory = new FruitFactory();
// 约定一个标识让工厂去生成,这里可以用反射的方式演进得更合理
Fruit fruit = fruitFactory.getFurit(Apple.class);
fruit.produce();
// 反射的相关代码
public Fruit getFruit(Class c) {
Fruit fruit = null;
fruit = (Fruit) Class.forName(c.getName()).newInstance();
return fruit;
}
2. 工厂方法
业务场景:拓展同类产品
好处:当需要增加同类产品时候,只需要新增加一个工厂,再新增一个产品类即可,不用改之前的代码。
// 工厂方法
VideoFactory videoFactory = new JavaVideoFactory();
Video video = videoFactory.getVideo();
video.produce();
思考问题:当前需要抽象出一个具体的课程, Java课程 = Java视频 + Java手记。 需要维护的是课程的增加和删除,同时保持视频和手记的编辑功能。换句话说,视频、手记同时依赖课程的时候,使用工厂方法还合理吗?
3. 抽象工厂
业务场景:同样是拓展同类产品,但是一类产品下有多个属性,比如一个课程有多个属性,分别是视频、手记
好处:完成了课程属性与应用层的解耦。
CourseFactory courseFactory = new JavaCourseFactory();
Video video = courseFactory.getVideo();
Article article = courseFactory.getArticle();
video.produce();
article.produce();
该业务场景下,将属性抽象成标准,每个产品都可以实现属性
如视频和手记设立一个标准,每个课程都有这两个属性,拓展一个新课程时需要新增课程工厂,还有新增对应属性的实现类。
工厂方法和抽象工厂的区别
首先要明白【产品等级】和【产品族】的区别
产品等级: 美的空调、格力空调、松下空调 | java课程、python课程、C++课程
产品族:美的空调、美的电饭煲、美的洗衣机 | java视频、java手记、java源码
工厂方法面向 方便拓展【产品等级】
抽象工厂面向 方便拓展【产品族】
结论
1.使用工厂方法,可以优雅地增加产品等级
如已存在【java视频、python视频】,现新增【C++视频】。
public abstract class VideoFactory { // java视频工厂、python视频工厂、C++视频视频工厂,继承videoFactory,设置get方法
public abstract Video getVideo();
}
public abstract class Video { // java视频、python视频、C++视频,继承video, 需要定义不同视频的内容或生产逻辑
public abstract void produce();
}
- 工厂方法应用层
VideoFactory videoFactory = new JavaVideoFactory();
Video video = videoFactory.getVideo();
video.produce();
- 使用抽象工厂,可以增加一个产品同时优雅地增加产品族。
如已存在课程的可选性【视频、手记、源码】 => java 课程、python课程都有这三个属性。
C++的课程:先初始化【C++视频、C++手记、C++源码】,后期可对这三个属性都可以在独立的代码里修改。
但是 一旦增加课程属性,如增加【C++作业】,那么改动抽象工厂的代码的工作量远大于工厂方法。
public interface CourseFactory {
// 这三个方法放在一起,牺牲了维护成本,提高了复杂业务的实现能力
Video getVideo();
Article getArticle();
Source getSource();
}
public abstract class Article {
public abstract void produce();
}
public abstract class Video {
public abstract void produce();
}
public abstract class Source{
public abstract void produce();
}
工厂方法复杂度较低,处理的业务场景简单。
抽象工厂复杂度较高,处理的业务场景复杂,但是产品族的需求变动会导致代码大量改动。