抽象工厂模式 : 提供一个创建一系列相关的或相互依赖对象的接口,而无需指定它们具体的类。
1. 在这个设计模式中,有抽象工厂接口, AbstracFactory Class 。这个接口有两个方法,分别用来创建抽象 Animal 和 抽象 Fruit 。也就是说,它会分别创建Animal 和 Fruit ,但具体不确定到底是 创建 Animal 中的 Bear 还是 Cat ,创建 Fruit 中的 Banana 还是 Apple。
2. 类似于前面两种工厂 类,抽象工厂模式有两个抽象产品,分别是 Animal 和 Fruit 。当然也可以再添加抽象产品 Human 之类的,但 这个时候就可能要在 工厂类中添加 createHuman 方法。
3. 分别有cat,bear 类继承了 Animal 类, Apple ,banana 类继承了Fruit。 其中Bear 类重写了 shout() 方法,用来表示Bear 和 Cat 是两个不同的产品。同样Apple 类重写了 eat() 方法来表示和 Banana 的不同实现。
4. 建立一个具体工厂类SpecificFactory1来implements 抽象工厂,并实现了 createAnimal () 和 createFruit() 方法,来创建一个 Bear 和 一个 Apple
5. 建立一个具体工厂类SpecificFactory12来implements 抽象工厂,并实现了 createAnimal () 和 createFruit() 方法,来创建一个 Bear 和 一个 Banana 。
6. 建立TestAbstractFactory 类来测试实验结果:
1. 先声明一个抽象工厂AbstractFactory,接着 用具体工厂SpecificFactory1 来对它赋值
2. 分别创建一个 抽象Fruit 类和一个 抽象Animal 类,
3. 调用 Fruit 的eat() 方法 和 调用 Animal 的 shout() 方法
从这里的逻辑可以看出,关键在于我们用了哪一个具体工厂来给 AbstractFactory 赋值,赋值不一样,那么产生的两个产品类也不一样,最后导致产品类调用 eat 和 shout 方法产生的结果不一样。
如果将
AbstractFactory factory = new SpecificFactory1();
改成
AbstractFactory factory = new SpecificFactory2();
其他地方代码不变,那么结果将是:
you create a bear in Bear class
you eat a :Banana
最后的讨论:
为什么要使用抽象工厂?
根据上面的实验结果,可以知道,用户需要创建两种产品,但具体着两种产品中的哪两个产品可能会随着时间的变化而变化。一个种类的产品的差异在于其具体实现不同,但有其共同点。通俗地讲,用户需要一个宠物和一个水果,他需要一个宠物来陪他,还需要一个水果吃。但是用户只喜欢宠物中的Bear 和 Cat ,也只喜欢 水果中的 Apple 和BANANA 。但现在不确定到底是要宠物中的Bear 或Cat,水果中的Apple 或 Banana。那么这个时候,就应该抽象出一个 Animal 类和一个 Fruit 类,Animal 类中有shout 方法类陪他解闷,Fruit 类中eat() 方法类给他填饱肚子。
因为他只需要一个 Animal 和一个 Fruit ,假设我们一开始就建立一个具体工厂来分别创建一个 Bear 类 和 一个Apple 类。如果用户这个时候喜欢 Bear 和 BANANA 的组合,那么我们就得修改 这个具体工厂类,让其创建一个Bear 类和一个 BANANA类,假设用户的需求一直在变化,那么我们就得一直更改这个具体工厂。如果修改的地方多了,那么我们在改代码的时候就非常容易出错。
这个时候就建立一个 抽象工厂,来创建 一个抽象 的Animal 和一个抽象的 Fruit。然后建立一个具体工厂来Implements 抽象工厂,并实现了createFriut () 和 createAnimal() ,用来创建 Bear 和 Apple 组合。并在用户代码中使用多态来的方式来创建Animal 类和Fruit 类。
AbstractFactory factory = new SpecificFactory2();
Animal animal = factory.createAnimal();
Fruit fruit = factory.createFruit();
如果用户不喜欢Bear 和Apple 组合,改成了喜欢 Cat 和 Banana 组合,那么我就再建议一个 具体工厂类,来分别创建一个 Cat 类 和一个Banana 类,而只需要在用户代码中 将SpecificFactory2 改成 SpecificFactoryX 就可以了,除了新建的具体工厂类,其他地方的代码都不用做修改。