工厂模式详解【简单工厂模式、工厂方法模式、抽象工厂模式】

文章目录:

1. 工厂模式介绍

工厂模式(Factory Pattern) 是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

简单来说就是: 我们创建一个工厂类,然后当调用者想要创建一个对象时,只需要告诉工厂类即可,由工厂类去创建对象,调用者无需知道是如何创建的,也不用自己去创建。

再形象点说就是: 比如我们需要购买一批电脑,我们只要把我们的需求告诉电脑工厂,电脑工厂就会帮我们把这批电脑做好,而我们是不用自己去做这个电脑的,也不用我们自己去知道这个电脑是怎么做出来的,这就是工厂模式。

工厂模式分为简单工厂模式工厂方法模式抽象工厂模式,它们都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。

下面就分别来看一下3种工厂模式。

2. 工厂模式——简单工厂模式

2.1 简单工厂模式介绍

简单工厂,简单工厂,自然是实现很简单。简单工厂模式只是将不同对象的创建操作进行了一层简单的封装,其实也就是把不同对象的创建操作全都单独放到一个类中,这个类就成为了简单工厂类;当我们需要某个对象时,只需把我们的需求告诉这个简单工厂类,然后由这个简单工厂类根据我们的需求去创建对应的对象即可。

2.2 简单工厂模式实现

  • 我们以电脑为例子,实现一个电脑工厂,由电脑工厂根据需求生成不同品牌的电脑。

1. 创建一个电脑抽象类

public abstract class Computer {
    public abstract void use();
}

2. 创建继承了电脑抽象类的,具体的不同品牌的电脑的实体类

public class HaseeComputer extends Computer {
    public HaseeComputer() {
        System.out.println("生产了神舟电脑");
    }

    @Override
    public void use() {
        System.out.println("使用了神舟电脑");
    }
}
public class LenovoComputer extends Computer {
    public LenovoComputer() {
        System.out.println("生产了联想电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了联想电脑");
    }
}

3. 创建一个电脑工厂

public class ComputerFactory {
    public static Computer produceComputer(String computerBrand) {
        if (computerBrand == null) {
            return null;
        }
        if (computerBrand.equalsIgnoreCase("Hasee")) {
            return new HaseeComputer();
        }else if (computerBrand.equalsIgnoreCase("Lenovo")) {
            return new LenovoComputer();
        }
        return null;
    }
}

4. 测试:使用工厂生产不同品牌电脑并使用

public class FactoryTest {
    public static void main(String[] args) {
        ComputerFactory computerFactory = new ComputerFactory();
        Computer haseeComputer = computerFactory.produceComputer("Hasee");
        haseeComputer.use();
        Computer  lenovoComputer = computerFactory.produceComputer("Lenovo");
        lenovoComputer.use();
    }
}

2.3 简单工厂模式的优缺点

优点: 简单工厂模式可以根据需求,动态生成使用者所需类的对象,而使用者不用去知道怎么创建对象,使得各个模块各司其职,降低了系统的耦合性。

缺点: 扩展性差,违背了开闭原则(开闭原则指的是:软件实现应该对扩展开放,对修改关闭)。新增产品时,需要修改工厂类。

比如上面的实现样例中,如果我们需要一个苹果电脑时,原有的工厂类就无法生产这个苹果电脑了,这个时候就需要去修改工厂类了。

3. 工厂模式——工厂方法模式

3.1 工厂方法模式的介绍

在简单方法中,我们是只有一个工厂类,由这个工厂类负责动态的创建我们所需要的对象;而在工厂方法模式中,我们的工厂类下面还有很多子工厂类,我们需要的对象是由这些子工厂类来创建的。其实就是改进了简单工厂模式,因为当我们需要一个新产品时,只需要扩展一个新的子工厂类即可,而不用去修改原有的代码,这样就符合了开闭原则。

3.2 工厂方法模式的实现

  • 我们还说以电脑为例子,实现一个电脑工厂,再根据不同品牌实现电脑工厂子类,由电脑工厂子类根据需求生成不同品牌的电脑。

1.创建一个电脑抽象类

public abstract class Computer {
    public abstract void use();
}

2.创建继承了电脑抽象类的,具体的不同品牌的电脑的实体类

public class LenovoComputer extends Computer {
    public LenovoComputer() {
        System.out.println("生产了联想电脑");
    }
    @Override
    public void use() {
        System.out.println("生产了联想电脑");
    }
}
public class HaseeComputer extends Computer {
    public HaseeComputer() {
        System.out.println("生产了神舟电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了神舟电脑");
    }
}

3.创建一个电脑抽象工厂类

public abstract class ComputerFactory {
    public abstract Computer produce();
}

4.创建电脑抽象工厂类的子类(根据不同的电脑品牌)

public class LenovoFactory extends ComputerFactory {
    @Override
    public Computer produce() {
        return new LenovoComputer();
    }
}
public class HaseeFactory extends ComputerFactory {
    @Override
    public Computer produce() {
        return new HaseeComputer();
    }
}

5. 测试:使用不同子工厂生产不同品牌电脑并使用

public class FactoryTest {
    public static void main(String[] args) {
        ComputerFactory haseeFactory = new HaseeFactory();
        Computer haseeComputer = haseeFactory.produce();
        haseeComputer.use();
        
        ComputerFactory lenovoFactory = new LenovoFactory();
        Computer lenovoComputer = lenovoFactory.produce();
        lenovoComputer.use();
    }
}

3.3 工厂方法模式的优缺点

优点: 扩展性好,符合了开闭原则,新增一种产品时,只需增加改对应的产品类和对应的工厂子类即可。比如样例实现中,当我们需要一个苹果电脑时,只需要去新增一个苹果电脑类和一个苹果工厂类即可,而无需去修改原有的代码。符合单一职责原则,每个工厂只负责一种产品,而不是由一个工厂去生成所有商品。

缺点: 当我们新增产品时,还需要提供对应的工厂类,系统中类的个数将会成倍增加,相当于增加了系统的复杂性。

4. 工厂模式——抽象工厂模式

4.1 抽象工厂模式的介绍

抽象工厂模式有点像是工厂方法模式的升级版。

工厂方法模式针对的某一种产品,而抽象工厂模式可以针对多种产品。

意思就是:工厂方法模式解决的是生产不同品牌的同一类型的电脑。而抽象工厂模式解决的是生产不同品牌的多种类型的电脑。

再白话些就是:工厂方法模式中的 联想电脑工厂 只能生产老式的台式电脑,而如果现在需要生产 台式电脑,笔记本电脑,平板电脑 等多个种类的电脑的话,那么工厂方法模式就不太方便了。而抽象工厂模式可以解决 联想电脑工厂 生产多个种类电脑的问题,也就是解决一个工厂生产多种类型的产品的问题。

4.2 抽象工厂模式的实现

  • 我们依旧用电脑为列子,实现一个电脑工厂,再根据不同品牌实现电脑工厂子类,由电脑工厂子类根据需求生成不同品牌的不同种类的电脑。

1. 创建各种类型的电脑抽象类

public abstract class DesktopComputer {
    public abstract void use();
}
public abstract class NotebookComputer {
    public abstract void use();
}

2. 创建具体的不同品牌的各种类型的电脑实体类

public class HaseeDesktopComputer extends DesktopComputer {
    public HaseeDesktopComputer() {
        System.out.println("生产了神舟台式电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了神舟台式电脑");
    }
}
public class HaseeNotebookComputer extends NotebookComputer {
    public HaseeNotebookComputer() {
        System.out.println("生产了神舟笔记本电脑");
    }
    @Override
    public void use() {
        System.out.println("生产了神舟笔记本电脑");
    }
}
public class LenovoDesktopComputer extends DesktopComputer {
    public LenovoDesktopComputer() {
        System.out.println("生产力联想台式电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了联想台式电脑");
    }
}
public class LenovoNotebookComputer extends NotebookComputer {
    public LenovoNotebookComputer() {
        System.out.println("生产了联想笔记本电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了联想笔记本电脑");
    }
}

3. 创建一个电脑的抽象工厂类

public abstract class ComputerFactory {
    public abstract DesktopComputer produceDesktopComputer();
    public abstract NotebookComputer produceNotebookComputer();
}

4. 创建电脑抽象工厂类的子类(根据不同的电脑品牌)

public class HaseeFactory extends ComputerFactory {
    @Override
    public DesktopComputer produceDesktopComputer() {
        return new HaseeDesktopComputer();
    }

    @Override
    public NotebookComputer produceNotebookComputer() {
        return new HaseeNotebookComputer();
    }
}
public class LenovoFactory extends ComputerFactory {
    @Override
    public DesktopComputer produceDesktopComputer() {
        return new LenovoDesktopComputer();
    }

    @Override
    public NotebookComputer produceNotebookComputer() {
        return new LenovoNotebookComputer();
    }
}

5. 测试:使用不同子工厂创建不同品牌的不同种类的电脑

public class TestFactory {
    public static void main(String[] args) {
        ComputerFactory haseeFactory = new HaseeFactory();
        DesktopComputer haseeDesktopComputer = haseeFactory.produceDesktopComputer();
        haseeDesktopComputer.use();
        NotebookComputer haseeNotebookComputer = haseeFactory.produceNotebookComputer();
        haseeNotebookComputer.use();

        ComputerFactory lenovoFactory = new LenovoFactory();
        DesktopComputer lenovoDesktopComputer = lenovoFactory.produceDesktopComputer();
        lenovoDesktopComputer.use();
        NotebookComputer lenocoFactory  = lenovoFactory.produceNotebookComputer();
        lenocoFactory.use();

    }
}

4.3 抽象方法模式的优缺点

优点: 工厂抽象类创建了多个类型的产品,当有需求时,可以创建相关产品子类和子工厂类来获取。也就是可以满足生产不同品牌的不同类型的电脑。

简单来说就是: 开始我们的工厂方法模式,如果我们需要台式电脑,又需要笔记本电脑,要多种产品时,工厂方法模式无法满足我们的需求;而抽象方法模式,提前在抽象工厂中,定义好了可能需要的多种产品,比如 台式电脑,笔记本电脑,平板电脑等,当有需求的时候,我们只需要创建相关子类和相关子工厂类即可。

缺点: 扩展新种类产品时困难。抽象工厂模式需要我们在工厂抽象类中提前确定了可能需要的产品种类,以满足不同品牌的多种产品的需求。但是如果我们需要的产品种类并没有在工厂抽象类中提前确定,那我们就需要去修改工厂抽象类了,而一旦修改了工厂抽象类,那么所有的工厂子类也需要修改,这样显然扩展不方便。

<span style="color: #FF6F00; ">猿兄碎碎念:</span>
大家可能一开始对于这3种工厂模式的理解有些混淆,没有关系,猿兄我刚看的时候也没太理解三者的区别,但是我去把3种工厂模式都实现了一遍,然后再将代码和思想结合来琢磨和理解,就明白了三种的区别和思想了。所以猿兄建议大家一定要<span style="color: #FF6F00; "> 多去动手实现,多去操作,再结合思想来琢磨,</span>才能更好的理解一个知识。

以上就是猿兄给大家带来的关于 工厂模式 的内容了。Spring 中的 BeanFactory 就是工厂模式中的简单工厂模式的体现,大家可以去看看相关内容。然后我们平时设计程序时,也可以考虑使用工厂模式的思想,对于优秀的程序设计是有很大的帮助的。

注:如果猿兄这篇博客有任何错误和建议,欢迎大家留言,不胜感激!

</br>
<span style="font-size:1.3em;font-weight: bold;">点个关注,不再迷路</span>

这里是<span style="color: #FF6F00; "> 猿兄</span>,为你分享程序员的世界。

非常感谢各位<span style="color: #FF6F00; ">优秀的程序员</span>们能看到这里,如果觉得文章还不错的话,<span style="color: #FF6F00; ">求点赞👍 求关注💗 求分享👬,</span>对我来说真的 <span style="color: #FF6F00; ">非常有用</span>!!!

持续更新文章,欢迎微信搜索: <span style="color: #FF6F00; "> 猿兄</span> 。第一时间获取最新文章,回复【<span style="color: #FF6F00; ">电子书</span>】还可免费获取我为大家准备的各类技术书籍。

</br>

本文由博客一文多发平台 OpenWrite 发布!

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

推荐阅读更多精彩内容