设计模式:(2)抽象工厂(Abstract Factory)

本文深入讲解了抽象工厂模式的概念、特点及其应用场景。通过对比工厂方法模式,阐明了抽象工厂模式如何为创建一系列相关或相互依赖的对象提供接口。并通过具体代码示例展示了其在耐克运动产品系列中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在分享抽象工厂模式前,我想还是将设计模式的分类图贴上,以便查看整体分布情况,防止思路混乱。

从设计模式分类图中可以看到抽象工厂模式是经典的创建型设计模式之一。也可以看到抽象工厂模式是对象型创建模式。

阅读过我分享的《设计模式:(1)工厂方法模式》的朋友一定对工厂方法模式的特点和作用有些了解了。工厂方法模式封装了一类产品创建组装的细节,使调用者不会参与到产品的组装细节当中,这样就会使调用者轻松的实现对所需产品(对象)的获取,也降低了对象间的耦合,使系统的可扩展性增强。

工厂方法模式只是针对一类产品的创建,而今天所要分享的抽象工厂模式是针对一系列产品的创建。

首先在面向对象的开发中我们经常会发现在某一个对象中同时依赖两个以上的不同种类的对象,这两个不同的依赖对象就是一系列产品。也就是说对于一个对象A他的出现必然会依赖一组对象B1,B2,B3....等等,参照依赖一个对象的获取使用工厂方法模式,那么一系列的依赖对象就采用抽象工厂模式

意图:为创建一组相关或相互依赖的对象提供一个接口,无需指定它们的具体类。

特点:

  • 抽象工厂模式是工厂方法模式的进一步衍生,针对的是一族(系列)产品。每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式针对的是多个产品等级结构。

  • 可用来生产不同产品族的全部产品。

  • 实现了创建者和调用者的分离。

适用情况:

  • 一个系统要独立于它的产品的创建、组合和表示时。
    一个系统要由多个产品系列中的一个来配置时。

  • 需要强调一系列相关的产品对象的设计以便进行联合使用时。

  • 提供一个产品类库,而只想显示它们的接口而不是实现时。

结构UML图:

从类图中可以看到,抽象工厂是由四种角色组成,与工厂方法模式的角色类相似,其中:

  • AbstractFactory 抽象工厂接口,声明一个创建抽象产品对象的操作接口。
  • ConcreteFactory 具体工厂类,实现创建具体产品的操作。
  • AbstractProduct 抽象产品接口,为一类产品对象创建一个接口。
  • Product 具体产品,定义一个将被相应的具体工厂创建的产品对象,实现AbstractProduct接口。
  • Client 客户端,仅使用由AbstractFactory和AbstractProduct声明的接口。

模式标准代码:

//产品A

interface ProductA {

   publicvoid method1();

   publicvoid method2();

   // 更多产品逻辑.....

}

 

// 产品B

interface ProductB {

   publicvoid method1();

   publicvoid method2();

   // 更多产品逻辑.....

}

 

// 产品A具体实现:等级为1的产品A

class ProductA1 implements ProductA {

 

   @Override

   publicvoid method1() {

      System.out.println("等级为1的产品A的逻辑");

   }

 

   @Override

   publicvoid method2() {

      // 业务逻辑处理代码

   }

 

   // 更多产品逻辑.....

}

 

// 产品A具体实现:等级为2的产品A

class ProductA2 implements ProductA {

 

   @Override

   publicvoid method1() {

      System.out.println("等级为2的产品A的逻辑");

   }

 

   @Override

   publicvoid method2() {

      // 业务逻辑处理代码

   }

   // 更多产品逻辑.....

}

 

// 产品B具体实现:等级为1的产品B

class ProductB1 implements ProductB {

 

   @Override

   publicvoid method1() {

      System.out.println("等级为1的产品B的逻辑");

   }

 

   @Override

   publicvoid method2() {

      // 业务逻辑处理代码

   }

   // 更多产品逻辑.....

}

 

// 产品B具体实现:等级为2的产品B

class ProductB2 implements ProductB {

 

   @Override

   publicvoid method1() {

      System.out.println("等级为2的产品B的逻辑");

   }

 

   @Override

   publicvoid method2() {

      // 业务逻辑处理代码

   }

   // 更多产品逻辑.....

}

 

// 抽象工厂接口

interface AbstractFactory {

   public ProductA createProductA();

   public ProductB createProductB();

   // 更多创建产品.....

}

 

// 具体工厂1:创建等级为1的A、B产品

class ConcreateFactory1 implements AbstractFactory {

 

   @Override

   public ProductA createProductA() {

      returnnew ProductA1();

   }

 

   @Override

   public ProductB createProductB() {

      returnnew ProductB1();

   }

   // 更多代码逻辑......

}

 

// 具体工厂1:创建等级为2的A、B产品

class ConcreateFactory2 implements AbstractFactory {

 

   @Override

   public ProductA createProductA() {

      returnnew ProductA2();

   }

 

   @Override

   public ProductB createProductB() {

      returnnew ProductB2();

   }

   // 更多代码逻辑......

}

 

// 客户端

publicclass Client {

   publicstaticvoid  main(String[] args) {

 

      // 定义两个工厂,等级为1和等级为2

      ConcreateFactory1  factory1 = new  ConcreateFactory1();

      ConcreateFactory2  factory2 = new  ConcreateFactory2();

 

      // 定义不同等级的A产品

      ProductA  a1 = factory1.createProductA();

      ProductA  a2 = factory2.createProductA();

 

      // 定义不同等级的B产品

      ProductB  b1 = factory1.createProductB();

      ProductB  b2 = factory2.createProductB();

 

      // 调用产品的业务逻辑

      a1.method1();

      b1.method1();

      a2.method1();

      b2.method1();

 

      // 更多业务逻辑....

   }

}

运行结果:

等级为1的产品A的逻辑
等级为1的产品B的逻辑
等级为2的产品A的逻辑
等级为2的产品B的逻辑

应用场景例子:

抽象工厂的优点不言而喻,下面我们以耐克体育运动品牌为例子加以巩固。我们知道,耐克是一个体育用品生产商,并且我们也很熟悉耐克运动装和运动鞋。假设耐克只是生产运动装和运动鞋,并且运动装有专业档次的和普通档次的,当然不同的档次的价格和材料不同,同样运动鞋也有不同档次的,不同档次的价格和材料也不同,这样耐克生产的产品如下:

//NIKE运动鞋

interface INIKESportsShoes {

   public String getShoesInfo();

   public Double getShosePrice();

}

 

//NIKE运动装

interface INIKESportswear {

   public String getSportswearInfo();

   public Double getSportswearPrice();

}

 

//Nike专业运动鞋

class NikeSpecialSportsShoes implements INIKESportsShoes {

 

   @Override

   public String getShoesInfo() {

      return"原装进口,拥有高强度防滑和脚部保护特性";

   }

 

   @Override

   public Double getShosePrice() {

      return 8888.99;

   }

 

}

 

//Nike 普通运动鞋

class NikeNormSportsShoes implements INIKESportsShoes {

 

   @Override

   public String getShoesInfo() {

      return"Made  in China,一般防滑和脚步保护";

   }

 

   @Override

   public Double getShosePrice() {

      return 489.99;

   }

 

}

 

//Nike 专业运动装

class NikeSpecialSportswear implements INIKESportswear {

 

   @Override

   public String getSportswearInfo() {

      return"原装进口,高强度防刮防擦破和四肢防护功能并提供夜晚荧光功能";

   }

 

   @Override

   public Double getSportswearPrice() {

      return 9998.99;

   }

 

}

 

//Nike 普通运动装

class NikeNormSportswear implements INIKESportswear {

 

   @Override

   public String getSportswearInfo() {

      return"Made  in China,一般防雨和防晒特性";

   }

 

   @Override

   public Double getSportswearPrice() {

      return 998.88;

   }

 

}

 

//NIKE运动产品

interface INIKESportProduct {

   public INIKESportsShoes getNikeSportsShoes();

   public INIKESportswear getNikeSportswear();

}

 

//Nike 专业运动产品

class NikeSpecialSportProduct implements INIKESportProduct {

 

   @Override

   public INIKESportsShoes getNikeSportsShoes() {

      returnnew NikeSpecialSportsShoes();

   }

 

   @Override

   public INIKESportswear getNikeSportswear() {

      returnnew NikeSpecialSportswear();

   }




}

 

//Nike 普通运动产品

class NikeNormSportProduct implements INIKESportProduct {

 

   @Override

   public INIKESportsShoes getNikeSportsShoes() {

      returnnew NikeNormSportsShoes();

   }

 

   @Override

   public INIKESportswear getNikeSportswear() {

      returnnew NikeNormSportswear();

   }

 

}

 

//一次去Nike专营店购买Nike产品的经历

publicclass  BuyNikeProduct {

   publicstaticvoid  main(String[] args) {

 

      // 实例化Nike体育产品

      INIKESportProduct  NikeSpecialSportProduct = new  NikeSpecialSportProduct();

      INIKESportProduct  NikeNormSportProduct = new  NikeNormSportProduct();

 

      // 买一件Nike专业运动装

      INIKESportswear  NikeSpecialSportswear = NikeSpecialSportProduct

           .getNikeSportswear();

 

      // 买一件普通的Nike运动鞋

      INIKESportsShoes  NikeNormSportShoes = NikeNormSportProduct

           .getNikeSportsShoes();

 

      // 看看产品状况

      System.out.println(”专业运动装:“+NikeSpecialSportswear.getSportswearInfo());

      System.out.println("普通运动鞋:"+NikeNormSportShoes.getShoesInfo());

 

      // 计算一下价格准备付款

      System.out.println("先生,价格是:");

      Double  price = NikeSpecialSportswear.getSportswearPrice()

           +  NikeNormSportShoes.getShosePrice();

      System.out.println(NikeSpecialSportswear.getSportswearPrice() + "+"

           +  NikeNormSportShoes.getShosePrice() + " 共 " + price

           +  " 付现金还是刷卡?");

      System.out.println("My  God ! You know what will happen!");

   }

}

购物结果:

专业运动装:原装进口,高强度防刮防擦破和四肢防护功能并提供夜晚荧光功能
普通运动鞋:Made in China,一般防滑和脚步保护
先生,价格是:
9998.99+489.99 共 10488.98 付现金还是刷卡?
My God ! You know what will happen!

从抽象工厂的UML图和例子代码分析总结出其优缺点如下:

抽象工厂的优点:

  • 具体产品从客户代码中被分离出来

  • 容易改变产品的系列

    将一个系列的产品族统一到一起创建

抽象工厂的缺点:

对于新增加的产品,无能为力,支持增加产品族, 在产品族中扩展新的产品是很困难的,它需要修改抽象工厂的接口。比如Nike产品增加了运动穿戴设备如智能手表该怎么办?只能重构产品族了。


------------------

写到这,又不觉叹息,又到周日了,眼看着马上就要上班了。但是,据说这一次有个小帮手来帮我干活,想到这,还是不午睡了,虽然已经下午17:21分了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值