【java设计模式】之 抽象工厂(Abstract Factory)模式

简介:

目录(?)[+]

1. 女娲的失误

        上一节学习了工厂模式,女娲运用了该模式成功创建了三个人种,可是问题来了,她发现没有性别……这失误也忒大了点吧……竟然没有性别,那岂不是……无奈,只好抹掉重来了,于是所有人都被消灭掉了,重新造人。

        女娲开始分析了,既然要区别男女,那么生产人种的工厂(八卦炉)要重新改造了,因为一个设备要么全男性,要么全女性。所以只能将八卦炉拆开了,把原先的一个变两个,并且略加修改,变成女性八卦炉和男性八卦炉,这样就可以了。于是女娲开始准备生产了,她先画了个示意图如下:

        这个图虽然有点大,但是不复杂,她将HumanFactory接口用两个新的接口继承,分别带有男性和女性特征;将原来具体的Human类也改成了抽象类,用两个具体的Human类去继承。下面我们看看女娲的实现:

        先看Human接口和它的几个抽象类:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //定义抽象人类接口  
  2. public interface Human {  
  3.     public void getColor();  
  4.     public void talk();  
  5.     public void getSex(); //多了个性别  
  6. }  
  7.   
  8. //定义抽象黄种人类  
  9. public abstract class AbstractYellowHuman implements Human {  
  10.     @Override  
  11.     public void getColor() {  
  12.         System.out.println("Yellow color");  
  13.     }  
  14.     @Override  
  15.     public void talk() {  
  16.         System.out.println("Yellow people");  
  17.     }   
  18. }   
  19. //抽象黑种人和白种人就不写了,跟抽象黄种人道理一样  
  20. //略  
  21.   
  22. //黄种人男性类  
  23. public class MaleYellowHuman extends AbstractYellowHuman {  
  24.     @Override  
  25.     public void getSex() {  
  26.         System.out.println("Yellow man!");  
  27.     }  
  28. }  
  29. //黄种人女性类略  
        以上省略了类似的代码,实现方式都一样,很简单,就不啰嗦了,到此为止,女娲把人种都定义好了,下面就是去定义八卦炉了:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //抽象工厂接口的定义  
  2. public interface HumanFactory {  
  3.     public Human createYellowHuman();  
  4.     public Human createBlackHuman();  
  5.     public Human createWhiteHuman();  
  6. }  
  7.   
  8. //生产女性的八卦炉  
  9. public class FemaleFactory implements HumanFactory {  
  10.     @Override  
  11.     public Human createYellowHuman() {  
  12.         return new FemaleBlackHuman();  
  13.     }  
  14.     @Override  
  15.     public Human createBlackHuman() {  
  16.         return new FemaleBlackHuman();  
  17.     }  
  18.     @Override  
  19.     public Human createWhiteHuman() {  
  20.         return new FemaleWhiteHuman();  
  21.     }  
  22. }  
  23.   
  24. //生产男性的八卦炉  
  25. public class MaleFactory implements HumanFactory {  
  26.     @Override  
  27.     public Human createYellowHuman() {  
  28.         return new MaleYellowHuman();  
  29.     }  
  30.     @Override  
  31.     public Human createBlackHuman() {  
  32.         return new MaleBlackHuman();  
  33.     }  
  34.     @Override  
  35.     public Human createWhiteHuman() {  
  36.         return new MaleWhiteHuman();  
  37.     }  
  38. }  
        好了,现在人种有了,八卦炉也有了,女娲终于可以再次造人了!

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class NvWa {  
  2.     public static void main(String[] args) {  
  3.         HumanFactory maleHumanFactory = new MaleFactory(); //第一条生产线:男性生产线  
  4.         HumanFactory femaleHumanFactory = new FemaleFactory(); //第二条生产线:女性生产线  
  5.           
  6.                 //生产线建立完毕,开始造人  
  7.         Human maleYellowHuman = maleHumanFactory.createYellowHuman(); //造黄色男性  
  8.         Human femaleYellowHuman = femaleHumanFactory.createYellowHuman(); //造黄色女性  
  9.           
  10.         System.out.println("--生产一个黄色女性--");  
  11.         femaleYellowHuman.getColor();  
  12.         femaleYellowHuman.talk();  
  13.         femaleYellowHuman.getSex();  
  14.           
  15.         System.out.println("--生产一个黄色男性--");  
  16.         maleYellowHuman.getColor();  
  17.         maleYellowHuman.talk();  
  18.         maleYellowHuman.getSex();  
  19.         /* 
  20.          * …… 
  21.          */  
  22.     }  
  23. }  
        到这里,抽象工厂模式的思路算是理清了,下面看看抽象工厂模式的定义。

2. 抽象工厂模式的定义

        抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式,其定义如下:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes. 即为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。它的通用类图如下:


        抽象工厂模式是工厂模式的升级版,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。我们来看看抽象工厂欧式的通用源代码,首先有两个互相影响的产品线(也叫产品族),例如汽车的左门和右门,这两个数量应该是相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结构约束的,我们先看看两个产品族的类图:


        注意类图上的圈圈、框框相对应,两个抽象的产品类可以有关系,例如共同继承或实现一个抽象类或接口,其源代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public abstract class AbstractProductA {  
  2.     //每个产品共有的方法  
  3.     public void shareMethod() {  
  4.       
  5.     }  
  6.     //每个产品相同的方法,不同的实现  
  7.     public abstract void doSomething();   
  8. }   
        两个具体的产品实现类的代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class productA1 extends AbstractProductA {  
  2.     public abstract void doSomething(){  
  3.         System.out.println("产品A1的实现方法");  
  4.     }  
  5. }   
  6.   
  7. public class productA2 extends AbstractProductA {  
  8.     public abstract void doSomething(){  
  9.         System.out.println("产品A2的实现方法");  
  10.     }  
  11. }   

        产品B与此类似,不再赘述。抽象工厂类AbstractCreator的职责是定义每个工厂要实现的功能,在通用代码中,抽象工厂类定义了两个产品族的产品创建,如下: 
 

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public abstract class AbstractCreator {  
  2.     //创建A产品家族  
  3.     public abstract AbstracProductA createProductA();  
  4.     //创建B产品家族  
  5.     public abstract AbstracProductB createProductB();  
  6.     //如果有N个产品族,这里就应该有N个创建方法  
  7. }   
        如何创建一个产品呢?这是由具体的实现类来完成的,Creator1和Creator2代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Creator1 extends AbstractCreator {  
  2.     //只生产产品等级为1的A产品  
  3.     public AbstracProductA createProductA(){  
  4.         return new ProductA1();  
  5.     }  
  6.     //只生产产品等级为1的B产品  
  7.     public AbstracProductB createProductB() {  
  8.         return new ProductB1();  
  9.     }   
  10. }   
  11.   
  12. public class Creator2 extends AbstractCreator {  
  13.     //只生产产品等级为1的A产品  
  14.     public AbstracProductA createProductA(){  
  15.         return new ProductA2();  
  16.     }  
  17.     //只生产产品等级为1的B产品  
  18.     public AbstracProductB createProductB() {  
  19.         return new ProductB2();  
  20.     }   
  21. }   

       注:有M个产品等级就应该有M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。 
 

       在具体的业务中就可以生产一个与实现无关的对象了,如:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class AbstractFactoryTest {  
  2.     public static void main(String[] args) {  
  3.         AbstractCreator creator1 = new Creator1();  
  4.         AbstractCreator creator2 = new Creator2();  
  5.         AbstractProductA a1 = creator1.createProductA();  
  6.         AbstractProductA a2 = creator2.createProductA();  
  7.   
  8.         AbstractProductB b1 = creator1.createProductB();  
  9.         AbstractProductB b2 = creator2.createProductB();  
  10.   
  11.         //……  
  12.     }  
  13. }  

 
 
 
 
 
 

3. 抽象工厂模式的优缺点

3.1 优点

        1)封装性。每个产品的实现类不是高层模块要关心的,它要关心的是接口,是抽象,它不关心对象是如何创建出来的,这都由工厂类负责的,只要知道工厂类是谁,我就能创建一个需要的对象,省时省力。

        2)产品族内的约束为非公开状态。例如生产男女比例的问题上,猜想女娲娘娘肯定有自己的打算,那么在抽象工厂模式中,这些约束都在工厂内里面实现的。

3.2 缺点

        抽象工厂模式最大的缺点就是产品族扩展非常困难。如果我们要增加一个产品C,也就是说产品族由原来的A和B增加到3个,那么我们首先要在抽象类AbstractCreator中增加createProductC()方法,然后两个实现类都要修改……说到这里,已经知道了扩展的弊端了……

        注意这里是产品族扩展比较困难,而不是产品等级扩展困难。产品等级扩展还是非常容易的,增加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。也就是说横向扩展容易,纵向扩展难。

        抽象工厂模式就介绍这么多,如有错误之处,欢迎留言指正~

       相关阅读:http://blog.csdn.net/column/details/des-pattern.html

_____________________________________________________________________________________________________________________________________________________

-----乐于分享,共同进步!

-----更多文章请看:http://blog.csdn.net/eson_15

相关文章
|
26天前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
43 0
[Java]23种设计模式
|
10天前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
1月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
1月前
|
设计模式 Java
Java设计模式
Java设计模式
28 0
|
1月前
|
设计模式 Java
Java设计模式之外观模式
这篇文章详细解释了Java设计模式之外观模式的原理及其应用场景,并通过具体代码示例展示了如何通过外观模式简化子系统的使用。
29 0
|
12天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
21天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
8天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
28 9
|
11天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
8天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin