聊聊常用设计模式(二)工厂方法模式和抽象工厂模式

1.工厂方法模式

 工厂方法模式(Factory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法模式让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所需产品对应的工厂,无需关心创建细节,而且加入新的产品时也符合开闭原则。
 工厂方法模式主要解决的是产品扩展问题。在简单工厂模式中,随着产品链的丰富,如果每个课程的创建逻辑有区别,则工厂的职责会变得越来越多。最后形成的臃肿结构不便于维护。根据单一职责原则,我们将职责继续划分,专人干转事。Java课程由Java工厂创建,Python课程由Python工厂创建,对工厂本身也做一个抽象。
来看代码,首先创建ICourseFactory接口:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 8:57 2020/4/11
 */
public interface ICourseFactory {

    ICourse create();

}

再分别创建子工厂,JavaCourseFactory的代码如下:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 9:05 2020/4/11
 */
public class JavaCourseFactory implements ICourseFactory {

    public ICourse create() {
        return new JavaCourse();
    }
}

PythonCourseFactory的代码如下:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 9:06 2020/4/11
 */
public class PythonCourseFactory implements ICourseFactory {
    public ICourse create() {
        return new PythonCourse();
    }
}

调用代码:

    public static void main(String[] args) {
        ICourseFactory factory = new PythonCourseFactory();
        ICourse course = factory.create();
        course.study();

        factory = new JavaCourseFactory();
        course = factory.create();
        course.study();
    }

来看一下类结构图:


类结构图

工厂方法模式适用于以下场景:
(1)创建对象需要大量重复的代码
(2)客户端(应用层)不依赖于产品类实例如何被创建、如何被实现等细节
(3)一个类通过其子类来指定创建哪个对象
工厂方法模式的缺点:
(1)类的个数过多,增加了代码编写的复杂度
(2)增加了系统的抽象性和理解难度

2.抽象工厂模式

 抽象工厂模式(Abstract Factory Pattern)是指提供一个创建一系列相关或相互依赖的接口,无须指定他们的具体类。客户端(应用层)不依赖于产品类的实例如何被创建、如何被实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
 如果对产品族和产品等级结构不了解的,可以通过以下链接学习:https://www.jianshu.com/p/5fb1e21c4d19

 好了上代码。还是以学习为例。现在单纯学习已经无法满足我们了,我们要养成良好的学习习惯,开始记笔记和做作业。在产品等级中增加两个产品,INote笔记和IWork作业。

IWork接口:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 9:58 2020/4/11
 */
public interface IWork {

    void write();

}

INote接口

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 9:57 2020/4/11
 */
public interface INote {

    void edit();

}

然后创建一个抽象工厂类CourseFactory:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:02 2020/4/11
 */
public interface CourseFactory {

    INote createNote();

    IWork createWork();

}

接下来,创建Java的产品族Java的笔记类JavaNote

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:06 2020/4/11
 */
public class JavaNote implements INote {
    public void edit() {
        System.out.println("编写Java笔记");
    }
}

扩展产品等级,新建Java的作业类JavaWork

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:14 2020/4/11
 */
public class JavaWork implements IWork {
    public void write() {
        System.out.println("完成Java作业");
    }
}

创建Java产品族的具体工厂JavaCourseFactory:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:17 2020/4/11
 */
public class JavaCourseFactory implements CourseFactory {
    public INote createNote() {
        return new JavaNote();
    }

    public IWork createWork() {
        return new JavaWork();
    }
}

然后创建Python产品的笔记类PythonNote:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:20 2020/4/11
 */
public class PythonNote implements INote {
    public void edit() {
        System.out.println("编写Python笔记");
    }
}

扩展产品等级,新建Python的作业类PythonWork

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:20 2020/4/11
 */
public class PythonWork implements IWork {
    public void write() {
        System.out.println("完成Python作业");
    }
}

创建Python产品族的具体工厂PythonCourseFactory:

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:25 2020/4/11
 */
public class PythonCourseFactory implements CourseFactory {
    public INote createNote() {
        return new PythonNote();
    }

    public IWork createWork() {
        return new PythonWork();
    }
}

来看调用代码

/**
 * @Author: zhouzhen
 * @email: zhouzhen0517@foxmail.com
 * @Description
 * @Date: Create in 10:28 2020/4/11
 */
public class AfpTest {
    public static void main(String[] args) {
        JavaCourseFactory factory = new JavaCourseFactory();
        factory.createNote().edit();
        factory.createWork().write();

        PythonCourseFactory factory1 = new PythonCourseFactory();
        factory1.createWork().write();
        factory1.createNote().edit();
    }
}

 上述代码完整的描述了两个产品族:Java课程和Python课程,也描述了两个产品等级作业和笔记。抽象工厂模式非常完美清晰的描述了这样一层复杂的关系。但是,如果我们要继续扩展产品等级,将比如考试也加入,那我们的代码从抽象工厂到具体工厂都要全部调整,很显然不符合开闭原则,所以抽象工厂也是有缺点的:
(1)规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
(2)增加了系统的抽象新和理解难度。
 但在实际应用中,产品等级结构升级是很正常的一件事情,只要不升级的过于频繁,可以根据实际情况不符合开闭原则,毕竟一切原则的本质都只是被使用的工具。

文章参考

《Spring5核心原理》〔中〕谭勇德(Tom)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容