抽象工厂模式 : 提供一个创建一系列相关的或相互依赖对象的接口,而无需指定它们具体的类。
1. 在这个设计模式中,有抽象工厂接口, AbstracFactory Class 。这个接口有两个方法,分别用来创建抽象 Animal 和 抽象 Fruit 。也就是说,它会分别创建Animal 和 Fruit ,但具体不确定到底是 创建 Animal 中的 Bear 还是 Cat ,创建 Fruit 中的 Banana 还是 Apple。
public interface AbstractFactory { public Animal createAnimal(); public Fruit createFruit(); }
2. 类似于前面两种工厂 类,抽象工厂模式有两个抽象产品,分别是 Animal 和 Fruit 。当然也可以再添加抽象产品 Human 之类的,但 这个时候就可能要在 工厂类中添加 createHuman 方法。
/** * 这是一个动物类,有一个所有动物都有的方法 shout * @author liaogang.pt */ public abstract class Animal { public void shout(){ System.out.println("you create a :"+this.getClass().getName()); } } /** * 这是一个抽象方法,有所有水果的共同方法 eat(),被人类吃。 * @author liaogang.pt * */ public abstract class Fruit { public void eat(){ System.out.println("you eat a :"+this.getClass().getName() + "in Fruit class"); } }
3. 分别有cat,bear 类继承了 Animal 类, Apple ,banana 类继承了Fruit。 其中Bear 类重写了 shout() 方法,用来表示Bear 和 Cat 是两个不同的产品。同样Apple 类重写了 eat() 方法来表示和 Banana 的不同实现。
/** * 这是一个熊类,简单起见,它继承了 Animal 类,同时也就继承了shout 方法 * @author liaogang.pt */ public class Bear extends Animal{ public void shout(){ System.out.println("you create a bear in Bear class" ); } } /** * 这是一个猫类,简单起见,它继承了 Animal 类,同时也就继承了shout 方法 * @author liaogang.pt */ public class Cat extends Animal{ }
public class Apple extends Fruit{ public void eat(){ System.out.println("you create a apple in Apple Class"); } } public class Banana extends Fruit{ }
4. 建立一个具体工厂类SpecificFactory1来implements 抽象工厂,并实现了 createAnimal () 和 createFruit() 方法,来创建一个 Bear 和 一个 Apple
public class SpecificFactory1 implements AbstractFactory { @Override public Animal createAnimal() { // TODO Auto-generated method stub return new Bear(); } @Override public Fruit createFruit() { // TODO Auto-generated method stub return new Apple(); } }
5. 建立一个具体工厂类SpecificFactory12来implements 抽象工厂,并实现了 createAnimal () 和 createFruit() 方法,来创建一个 Bear 和 一个 Banana 。
public class SpecificFactory2 implements AbstractFactory{ @Override public Animal createAnimal() { // TODO Auto-generated method stub return new Bear(); } @Override public Fruit createFruit() { // TODO Auto-generated method stub return new Banana(); } }
6. 建立TestAbstractFactory 类来测试实验结果:
1.先声明一个抽象工厂AbstractFactory,接着 用具体工厂SpecificFactory1 来对它赋值
2. 分别创建一个 抽象Fruit 类和一个 抽象Animal 类,
3. 调用 Fruit 的eat()方法 和 调用 Animal 的 shout() 方法
从这里的逻辑可以看出,关键在于我们用了哪一个具体工厂来给 AbstractFactory 赋值,赋值不一样,那么产生的两个产品类也不一样,最后导致产品类调用 eat 和 shout 方法产生的结果不一样。
public class TestAbstractFactory { public static void main(String[] args){ AbstractFactory factory = new SpecificFactory1(); Animal animal = factory.createAnimal(); Fruit fruit = factory.createFruit(); animal.shout(); fruit.eat(); } } 结果: you create a bear in Bear class you create a apple in Apple Class
如果将
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 就可以了,除了新建的具体工厂类,其他地方的代码都不用做修改。