设计模式——抽象工厂模式

抽象工厂模式

一、定义:

● 为创建一组相关或依赖的对象提供一个接口,而无需指定他们的具体类型。是工厂方法模式的升级版。

与工厂方法模式的区别:

● 1.工厂方法每个工厂只能创建一个类型的产品,而抽象工厂可以创建多个类型的产品。

● 2.工厂方法产出的一个产品(实例),抽象工厂是创建新工厂。

二、模式组成:

组成(角色)

关系

作用

抽象产品族(AbstractProduct)

抽象产品的父类

描述抽象产品的公共接口

抽象产品(Product)

具体产品的父类

描述具体产品的公共接口

具体产品(Concrete Product)

抽象产品的子类;工厂类创建的目标类

描述生产的具体产品

抽象工厂(Creator)

具体工厂的父类

描述具体工厂的公共接口

具体工厂(Concrete Creator)

抽象工厂的子类;被外界调用

描述具体工厂;实现FactoryMethod工厂方法创建产品的实例

三、使用步骤:

● 步骤1: 创建抽象工厂类,定义具体工厂的公共接口;

● 步骤2: 创建抽象产品族类 ,定义抽象产品的公共接口;

● 步骤3: 创建抽象产品类 (继承抽象产品族类),定义具体产品的公共接口;

● 步骤4: 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;

● 步骤5: 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;

● 步骤6: 客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例

注:有N个产品族,在抽象工厂中就应该有N个创建方法。

四、Demo解析:

demo描述:女娲造人,之前造了 黑皮肤和白皮肤两种肤色的人种,发现都是同一性别的,之后发生的事情就有点混乱(自己想象,哈哈) ,接下来女娲想造出两种不同性别,不同肤色的人。所以女蜗就创造了一个生产黑皮肤,一个生产白皮肤人类的工厂。

步骤1: 创建抽象工厂类,定义具体工厂的公共接口

public interface HumanFactory {
// 创建白皮肤产品族
Human createWhiteHuman();
// 创建黑皮肤产品族
Human createBlackHuman();
}

步骤2: 创建抽象产品族类 ,定义抽象产品的公共接口;

public interface Human {
    void getColor();

    void talk();

    void getSex();
}

步骤3: 创建抽象产品类 (继承抽象产品族类),定义具体产品的公共接口

  // 负责人种的公共属性的定义。
public abstract class AbstractBlackHuman implements Human {

  @Override
  public void getColor() {
      System.out.println("AbstractBlackHuman black");
  }

  @Override
  public void talk() {
      System.out.println("AbstractBlackHuman talk");
  }

  public abstract class AbstractWhiteHuman implements Human {

      @Override
      public void getColor() {
          System.out.println("AbstractWhiteHuman white");
      }

      @Override
      public void talk() {
          System.out.println("AbstractWhiteHuman talk");
      }
  }
}

步骤4: 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;

public class FemaleBlackHuman extends AbstractBlackHuman {

    @Override
    public void getSex() {
        System.out.println("FemaleBlackHuman 生产一个黑皮肤美女");
    }
}

public class FemaleWhiteHuman extends AbstractWhiteHuman {
    @Override
    public void getSex() {
        System.out.println("FemaleWhiteHuman 生产一个白皮肤美女");
    }
}

public class MaleBlackHuman extends AbstractBlackHuman {
    @Override
    public void getSex() {
        System.out.println("MaleBlackHuman 生产一个黑皮肤大汉");
    }
}

public class MaleWhiteHuman extends AbstractWhiteHuman {
    @Override
    public void getSex() {
        System.out.println("MaleWhiteHuman 生产一个白皮肤大汉");
    }
}

步骤5: 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;

// 生产美女的工厂
public class FemaleHumanFactory implements HumanFactory {
    @Override
    public Human createWhiteHuman() {
        return new FemaleWhiteHuman();
    }

    @Override
    public Human createBlackHuman() {
        return new FemaleBlackHuman();
    }
}

// 生产男性的工厂(区分颜色)
public class MaleHumanFactory implements HumanFactory {
    @Override
    public Human createWhiteHuman() {
        return new MaleWhiteHuman();
    }

    @Override
    public Human createBlackHuman() {
        return new MaleBlackHuman();
    }
}

步骤6:客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例

 // 生产男性的生产线
    FemaleHumanFactory femaleHumanFactory = new FemaleHumanFactory();
    // 生产女性的生产线
    MaleHumanFactory maleHumanFactory = new MaleHumanFactory();
    //开始产人
    Human blackHuman = femaleHumanFactory.createBlackHuman();
    blackHuman.getColor();
    blackHuman.talk();
    blackHuman.getSex();

    Human whiteHuman = maleHumanFactory.createWhiteHuman();
    whiteHuman.getColor();
    whiteHuman.talk();
    whiteHuman.getSex();

五、优缺点

优点:

● 1.封装性,降低耦合度:每个产品的实现类不是高层所关心的,只关心抽象和接口,不关心对象如何创建出来,由谁负责。只需知道工厂是谁,就能创建一个对象。

● 2.更符合开闭原则:新增一个产品类时,只需增加相应具体产品类和抽象工厂子类即可。

● 3.更符合单一原则:每个具体工厂类只负责创建相应的产品。

缺点:

● 扩展产品族困难,需要更改的代码太多。如果要增加一个产品 C, 也就是说产品家族由原来的 2 个增加到 3 个,看看我们的程序有多大改动吧! 抽象类 AbstractCreator 要增加一个方法 createProductC(), 然后两个实现类都要修改,想想看,这严重违反了开闭原则, 而且我们一直说明抽象类和接口是一个契约。

注:虽然抽象工厂模式扩展产品族困难,但是扩展产品类别比较容易,

原文发布于微信公众号 - Android机动车(JsAndroidClub)

原文发表时间:2018-03-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏学习力

《Java从入门到放弃》JavaSE入门篇:运算符

1636
来自专栏JMCui

工厂方法模式.

TOPIC:我们要定义一个披萨店,并允许个人或机构加盟,而且个人或机构可以根据当地不同的口味生产不同的披萨。

1163
来自专栏CSDN技术头条

抽象类和接口的区别

【编者按】本文作者是Sebastian Malaca,是面向对象编程的狂热者,不断深化研究整洁代码和高代码质量。本文中,作者通过多个方面深入剖析抽象类和接口的区...

21410
来自专栏C语言及其他语言

《黄老师问答笔录》之C语言常见易错问题

以下摘自黄老师课堂课堂答疑、与学生交流的真实问题总结,为了便于入学者学习查阅,总结归纳于此。 1、问:我想判断一个数字是否在一个区间里,比如if(90<a<10...

35513
来自专栏木制robot技术杂谈

谈一谈Python中str()和repr()的区别

前言 在学习BeautifulSoup文档的时候发现了一个以前不常见的Python内建函数repr(),带着好奇对这个内建函数进行了一番搜索和学习。 总结 s...

3464
来自专栏玄魂工作室

如何学python 第十七课 类-面向对象的概念

欢迎回来。今天要说的东西将会改变我们写程序的方式。今天我们介绍‘类’(class)。 概述 什么叫‘类’?类,类型。变量类型。从日常生活的感觉来说,‘类’其实...

2714
来自专栏Albert陈凯

scala的option和some

对于学习 Scala 的 Java™ 开发人员来说,对象是一个比较自然、简单的入口点。在 本系列 前几期文章中,我介绍了 Scala 中一些面向对象的编程方法,...

2925
来自专栏数据结构与算法

P1049 装箱问题

题目描述 有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30,每个物品有一个体积(正整数)。 要求n个物品中,任取若干个装入箱...

2915
来自专栏Python爬虫与数据挖掘

Python大神用一道题带你搞定Python函数中形参和实参问题

昨天在Python学习群里有位路人甲问了个Python函数中关于形参和实参一个很基础的问题,虽然很基础,但是对于很多小白来说不一定简单,反而会被...

1201
来自专栏Java后端技术栈

Java提供的排序算法是怎么实现的?快排?

前几天整理的一套面试题,其中有一个问题就是Java的JDK中我们见到的Collections.sort()和Arrays.sort()这两个排序算法的实现方式是...

1423

扫码关注云+社区

领取腾讯云代金券