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

本文介绍设计模式中的AbstractFactory模式,通过烹饪锅式料理的例子详细解释了抽象工厂模式的应用场景及其实现方式,展示了如何通过该模式确保对象一致性并简化代码。

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

8. AbstractFactory 模式

设计模式 第八章 AbstractFactory 模式

  • 8.1 所谓AbstractFactory模式是什么
  • 8.2 例子
  • 8.3 AbstractFactory 模式总结

8.1 所谓AbstractFactory模式是什么?

这一章节我们学习 AbstractFactory 模式AbstractFactory 直译成文是抽象工厂」。所谓抽象工厂究竟是怎样的工厂呢?AbstractFactory 模式,提供专门实现实例的生成的类,达到必须保持一致性的一系列对象准确无误地生成这个目的。

我们拿制造」的代码举个例子其中有一部分代码是向对象的变量 car 中添加轮胎和方向盘

car.addTire(new CarTire());
car.addHandle(new CarHandle());

上面的这种写法,在大多数时候没有问题。可是,也有可能发生由于程序员的不经意的失误造成意想不到的错误这种情况。比如原本要制造汽车的,却把自行车的轮胎给作为参数传递过去了。如下所示

car.addTire(new BicycleTire());
car.addHandle(new CarHandle());

在实际的汽车制造过程中,我们不会担心这样的错误,但是在程序编写的过程中我们往往会像上面那样使用了不该使用的对象。这个时候,我们预先定义一个能单独负责制造所需的对象的工厂类。当需要生成轮胎、方向盘等对象的时候我们使用这个工厂类来生成,这样就能避免上面的错误。同时、这个工厂类修改的时候、使用它的相关对象也能一股脑儿被修改。

8.2 例子

我们拿锅式料理的制造作为例子。锅式料理有很多种类,例如鸡肉汆锅鸡素烧汆锅泡菜汆锅肉圆汆锅鲑鱼汆锅。大体由以下的部分组成。

  • 主要成份(蛋白质)
  • 蔬菜
  • 其他成份

主要成份一般是指肉和鱼等含蛋白质的材料。我们把表示锅式料理的HotPot类定义成下面的样子。

public class HotPot{
                 private Pot pot;
                 private Soup soup;
                    private Protein protein;
                    private List vegetables;
                    private List otherIngredients;
                    public HotPot(Pot pot){
                                         this.pot = pot;
                    }
                    public void addSoup(Soup sopu){
                                         this.soup = soup;
                    }
                    public void addMain(Protein protein){
                                         this.protein = protein;
                    }
                    public void addVegetables(List vegetables){
                                         this.vegetables = vegetables;
                    }
                    public void addOtherIngredients(List otherIngredients){
                                         this.otherIngredients = ingredients;
                    }
}

使用的,我们用构造函数的参数来指定。,我们通过指定AddSoup方法的参数Soup来添加。在这里,我们没有定义Soup类,但可以把它看成是类的父类。接下来,addMain 方法,它使用 Protein 对象作为参数Protein 类这里也没有定义,但是可以把它看成是鸡肉、牛肉、豆腐等类的父类。蔬菜,我们通过指定addVegitables 方法的List类型的参数来添加。其他成份我们通过指定addOtherIngredients 方法的List类型的参数来添加。

首先我们来制作鸡肉汆锅这道料理。代码如下

public class SampleClass{
                   public static void main(String args[]){
                                         HotPot hotPot = new HotPot();
                                         hotPot.addSoup(new ChickenBonesSoup()); // 鶏がらを煮込んだスープ
                                         hotPot.addMain(new Chicken());        // Main として鶏肉
                                         List vegetables[] = new ArrayList();
                                         vegetables.add(new ChineseCabbage()); // 白菜
                                         vegetables.add(new Leek());           // ねぎ
                                         vegetables.add(new Chrysanthemum());  // 春菊
                                         hotPot.addVegetables(vegetables);
                                         List otherIngredients = new ArrayList();
                                         otherIngredients.add(new Tofu());     // 豆腐
                                         hotPot.addOtherIngredients(otherIngredients);
                    }
}

这样鸡肉汆锅料理就完成了。但是,依照编程人员的不同,使用这种编程手法会导致制作成不同的鸡肉汆锅料理(向蔬菜List添加蔬菜时编程人员A添加了卷心菜,B可能添加大白菜)。基于某种理由,有些时候我们可能需要防止这种情况发生。在这种情况下,我们先准备好了专门生成鸡肉汆锅对象的类,当我们想制作鸡肉汆锅的时候用这个类生成实体对象。我们把这个类叫做MizutakiFactoryMizutakiFactory类的代码如下

 public class MizutakiFactory{
                   public Soup getSoup(){
                                         return new ChickenBonesSoup();
                    }
                    public Protein getMain(){
                                         return new Chicken();
                    }
                    public List getVegetables(){
                                         List vegetables = new ArrayList();
                                         vegetables.add(new ChineseCabbage());
                                         vegetables.add(new Leek());
                                         vegetables.add(new Chrysanthemum);
                                         return vegetables;
                    }
                    public List getOtherIngredients(){
                                         List otherIngredients = new ArrayList();
                                         otherIngredients.add(new Tofu());
                                         return otherIngredients;
                    }
}

为了和这个类配合,我们把SampleClass类修改成如下的样子。

public class SampleClass{
                    public static void main(String args[]){
                                         HotPot hotPot = new HotPot();
                                         Factory factory = new MizutakiFactory();
                                         hotPot.addSoup(factory.getSoup());
                                         hotPot.addMain(factory.getMain());
                                         hotPot.addVegetables(factory.getVegetables());
                                         hotPot.addOtherIngredients(factory.getOthreIngredients());
                    }
}

当我们要制作鸡肉汆锅料理的时候,必须使用MizutakiFactory类,这样不管是什么人总归生成的是同一种鸡肉汆锅。也就是说,变为一种编程人员不易犯错的结构了。让我们来看看这种结构的类图吧。

クラス図1

现在虽然不是AbstractFactory模式,但是却能达到使被利用对象保持一致这样的要求

由于要制作和MizutakiFactory一样的SukiyakiFactoryKimuchiFactory等,我们作成了这些类的父类FactoryFactory类定义了以下getSoupgetMaingetVegetablesgetOtherIngredients四个抽象方法

public abstract class Factory{
                    public abstract Soup getSoup();
                    public abstract Protein getMain();
                    public abstract List getVegetables();
                    public abstract List getOtherIngredients();
}

SampleClass类的main方法中,根据赋值给参数的字符的不同,有选择性地创建实际使用的Factory

public class SampleClass{
                    public static void main(String args[]){
                                         HotPot hotPot = new HotPot();
                                         Factory factory = createFactory(args[0]);
                                         hotPot.addSoup(factory.getSoup());
                                         hotPot.addMain(factory.getMain());
                                         hotPot.addVegetables(factory.getVegetables());
                                         hotPot.addOtherIngredients(factory.getOthreIngredients());
                    }
                    private Factory createFactory(String str){
                                         if("泡菜汆锅".equals(str)){
                                                             return new KimuchiFactory();
                                         }else if("鸡素烧汆锅".equals(str){
                                                             return new SukiyakiFactory();
                                         }else{
                                                             return new MizutakiFactory();
                                         }
                    }
} 

main方法中,我们虽然不知道Factory实例的具体类型,但下面的处理仍然可以进行。也就是说,我们通过使用抽象的Factory类使得处理能够继续进行。像这样,就能满足使被利用的对象群体能够自由替换要求。下面就是这种情况的类图

クラス図2

8.3 AbstractFactory 模式总结

例子SampleClassmain方法,在没有明确究竟使用了Factory的那一个子类的情况下,我们却得到了能够被HotPot使用的对象。例如addSoup时的factory.getSoup()

AbstractFactory模式一般的类图如下所示。

AbstractFactory パターンの一般的なクラス図

[引用] Java言語で学ぶ デザインパターン入門』(結城浩 ソフトバンクパブリッシング株式会社出版 2001)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值