一听“工厂”就知道,肯定是产生产品的地方。不同的工厂可以生产不同的产品,如果没有区分工厂,就实际生活中,印度的小作坊,什么都能做,吃的喝的用的,全出自一个地方。这样对生产的产品来说是非常的混乱,不专业,而且产品种类太多,容易出现原材料缺失等等。。
有了工厂模式,就可以解决这些混乱的问题。咱们就拿CSDN首页左边拦的分类举例子把。“我是CSDN的编辑,现在我需要构造5个分类出来!”
public class BuildCategory {
public static void main(String[] args) {
System.out.println("建立类别:首页");
System.out.println("建立类别:博客");
System.out.println("建立类别:学习");
System.out.println("建立类别:下载");
System.out.println("建立类别:社区");
}
}
你有什么感想?如果我需要再建立“视频”和“GitCode”分类等等,那么该多么臃肿,对于使用者而言需要多写好多东西不说,还非常不易于维护。那怎么办?接下来就是简单工厂方法登场了。
简单工厂模式
public class EasyFactory {
public static void main(String[] args) {
EasyFactory easyFactory = new EasyFactory();
easyFactory.BuildCategory(1);
easyFactory.BuildCategory(2);
}
public void BuildCategory(int category) {
switch (category) {
case 1:
System.out.println("建立类别:首页");
case 2:
System.out.println("建立类别:博客");
case 3:
System.out.println("建立类别:学习");
case 4:
System.out.println("建立类别:下载");
case 5:
System.out.println("建立类别:社区");
}
}
}
这好像看着舒服多了,对于使用者而言(main函数)仅需通过对应的值就能得到我要的分类了,使用者根本就不需要关注内部细节,也不需要知道到底有多少分类,仅需提供一个int值就能构造出想要的分类了。
这就完美了?不对把!根本就没有解决代码臃肿的问题,如果要扩展多个分类,还需要在switch语句中增加,那么BuildCategory方法会越来越庞大,一旦写错,程序就会崩溃了。
工厂方法模式
首先我们先建立一个工厂的接口,专门构造分类
public interface Factory {
void createCategory();
}
而后,我们为每个分类都去实现这个工厂接口,这样就可以扩展出很多个分类工厂了
public static class IndexFactory implements Factory {
@Override
public void createCategory() {
System.out.println("建立类别:首页");
}
}
public static class BlogFactory implements Factory {
@Override
public void createCategory() {
System.out.println("建立类别:博客");
}
}
public static class StudyFactory implements Factory {
@Override
public void createCategory() {
System.out.println("建立类别:学习");
}
}
public static class DownloadFactory implements Factory {
@Override
public void createCategory() {
System.out.println("建立类别:下载");
}
}
public static class CommunityFactory implements Factory {
@Override
public void createCategory() {
System.out.println("建立类别:社区");
}
}
客户端代码
public static void main(String[] args) {
Factory indexFactory = new IndexFactory();
indexFactory.createCategory();
Factory blogFactory = new BlogFactory();
blogFactory.createCategory();
Factory studyFactory = new StudyFactory();
studyFactory.createCategory();
}
如果我们再去添加其他很多的分类,仅需实现工厂接口即可。这样既解决了简单工厂臃肿的问题,而且这里还遵循了设计模式的“开闭原则”,对扩展开放(实现工厂接口), 对修改关闭(新增分类修改BuildCategory方法)。
GOF对工厂方法模式的定义:工厂方法模式定义了一个创建对象的接口,但由子类决定实例化哪个类。工厂方法将对象的创建延迟到子类。
抽象工厂模式
我现在想仿CSDN也做个网站,那么就针对分类而言,虽然分类都一样,但是分类下的功能和CSDN有区别,怎么办?还像工厂模式一样,开始扩展,比如
public static class DirosIndexFactory implements Factory {
@Override
public void createCategory() {
System.out.println("建立Diros的专属类别:首页");
}
}
public static class DirosBlogFactory implements Factory {
@Override
public void createCategory() {
System.out.println("建立Diros的专属类别:博客");
}
}
我的专属就有5个和CSDN一样的分类,假如又有其他人也要模仿,虽然符合了开闭原则那么工厂类的数量会暴增的!后期还是不好维护。仔细思考下,既然分类都是人划分的,那同一功能点下应该属于一个系列。而抽象工厂解决的就是产品族创建的问题,它将同一系列产品的创建提取到了抽象工厂中。我们可以按照建站人创建不同分类族工厂:
public interface Factory {
void createIndex();
void createBlog();
void createStudy();
void createDownload();
void createCommunity();
}
接下来,我们就可以嗨皮的创建自己的专属分类工厂了~~
public static class DirosCategory implements Factory {
@Override
public void createIndex() {
System.out.println("建立Diros的专属类别:首页");
}
@Override
public void createBlog() {
System.out.println("建立Diros的专属类别:博客");
}
@Override
public void createStudy() {
System.out.println("建立Diros的专属类别:学习");
}
@Override
public void createDownload() {
System.out.println("建立Diros的专属类别:下载");
}
@Override
public void createCommunity() {
System.out.println("建立Diros的专属类别:社区");
}
}
public static class SuperManCategory implements Factory {
@Override
public void createIndex() {
System.out.println("建立SuperMan的专属类别:首页");
}
@Override
public void createBlog() {
System.out.println("建立SuperMan的专属类别:博客");
}
@Override
public void createStudy() {
System.out.println("建立SuperMan的专属类别:学习");
}
@Override
public void createDownload() {
System.out.println("建立SuperMan的专属类别:下载");
}
@Override
public void createCommunity() {
System.out.println("建立SuperMan的专属类别:社区");
}
}
我建立了Diros和SuperMan的专属分类网站,最后是客户端运行的代码:
public static void main(String[] args) {
Factory dirosFactory = new DirosCategory();
dirosFactory.createBlog();
dirosFactory.createDownload();
dirosFactory.createIndex();
Factory superManFactory = new DirosCategory();
superManFactory.createCommunity();
superManFactory.createStudy();
}
GOF对抽象工厂方法模式的定义:抽象工厂模式提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。
不过抽象工厂模式也有它的缺点,如果我再新增一种分类,那么无疑就要修改Factory的接口了,对应所有的实现类都要修改,这好像违反了开闭原则了。
总结
简单工厂模式简单容易使用,适合比较少的产品创建,缺点则是不符合开闭原则
工厂模式对于扩展新产品提供了便捷操作仅需实现工厂接口即可,缺点是如果产品多,实现类就会暴增
抽象工厂模式很好解决了产品族创建的问题,但是不太符合开闭原则,不过它也有解决办法,就是利用反射去创建(Go语言,c++都有反射)
总之这三种工厂模式都各有用途,在不同的场景应选用不同的模式