Java 设计模式 抽象工厂模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 设计模式 抽象工厂模式相关的知识,希望对你有一定的参考价值。

  场景:当装机工程师为不同的客户组装电脑时,根据客户的装机方案,获取相应的配件,然后组装。

  使用简单工厂模式:

  技术分享

  CPU接口:

1 public interface Cpu {
2     public void calculate();
3 }

  CPU接口具体实现类:

 1 public class IntelCpu implements Cpu {
 2     /**
 3      * CPU的针脚数
 4      */
 5     private int pins = 0;
 6     public  IntelCpu(int pins){
 7         this.pins = pins;
 8     }
 9     @Override
10     public void calculate() {
11         // TODO Auto-generated method stub
12         System.out.println("Intel CPU的针脚数:" + pins);
13     }
14 
15 }

 

 1 public class AmdCpu implements Cpu {
 2     /**
 3      * CPU的针脚数
 4      */
 5     private int pins = 0;
 6     public  AmdCpu(int pins){
 7         this.pins = pins;
 8     }
 9     @Override
10     public void calculate() {
11         // TODO Auto-generated method stub
12         System.out.println("AMD CPU的针脚数:" + pins);
13     }
14 }

 

  主板接口:

1 public interface Mainboard {
2     public void installCPU();
3 }

  主板接口具体实现类:

 1 public class IntelMainboard implements Mainboard {
 2     /**
 3      * CPU插槽的孔数
 4      */
 5     private int cpuHoles = 0;
 6     /**
 7      * 构造方法,传入CPU插槽的孔数
 8      * @param cpuHoles
 9      */
10     public IntelMainboard(int cpuHoles){
11         this.cpuHoles = cpuHoles;
12     }
13     @Override
14     public void installCPU() {
15         // TODO Auto-generated method stub
16         System.out.println("Intel主板的CPU插槽孔数是:" + cpuHoles);
17     }
18 
19 }

 

 1 public class AmdMainboard implements Mainboard {
 2     /**
 3      * CPU插槽的孔数
 4      */
 5     private int cpuHoles = 0;
 6     /**
 7      * 构造方法,传入CPU插槽的孔数
 8      * @param cpuHoles
 9      */
10     public AmdMainboard(int cpuHoles){
11         this.cpuHoles = cpuHoles;
12     }
13     @Override
14     public void installCPU() {
15         // TODO Auto-generated method stub
16         System.out.println("AMD主板的CPU插槽孔数是:" + cpuHoles);
17     }
18 }

 

  CPU工厂类:

 1 public class CpuFactory {
 2     public static Cpu createCpu(int type){
 3         Cpu cpu = null;
 4         if(type == 1){
 5             cpu = new IntelCpu(755);
 6         }else if(type == 2){
 7             cpu = new AmdCpu(938);
 8         }
 9         return cpu;
10     }
11 }

  主板工厂类:

 1 public class MainboardFactory {
 2     public static Mainboard createMainboard(int type){
 3         Mainboard mainboard = null;
 4         if(type == 1){
 5             mainboard = new IntelMainboard(755);
 6         }else if(type == 2){
 7             mainboard = new AmdMainboard(938);
 8         }
 9         return mainboard;
10     }
11 }

 

  装机工程师类:

 1 public class ComputerEngineer {
 2     /**
 3      * 定义组装机需要的CPU
 4      */
 5     private Cpu cpu = null;
 6     /**
 7      * 定义组装机需要的主板
 8      */
 9     private Mainboard mainboard = null;
10     public void makeComputer(int cpuType , int mainboard){
11         /**
12          * 组装机器的基本步骤
13          */
14         //1:首先准备好装机所需要的配件
15         prepareHardwares(cpuType, mainboard);
16         //2:组装机器
17         //3:测试机器
18         //4:交付客户
19     }
20     private void prepareHardwares(int cpuType , int mainboard){
21         //这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
22         //可是,装机工程师并不知道如何去创建,怎么办呢?
23         
24         //直接找相应的工厂获取
25         this.cpu = CpuFactory.createCpu(cpuType);
26         this.mainboard = MainboardFactory.createMainboard(mainboard);
27         
28         //测试配件是否好用
29         this.cpu.calculate();
30         this.mainboard.installCPU();
31     }
32 }

  

  客户端:

1 public class Client {
2     public static void main(String[]args){
3         ComputerEngineer cf = new ComputerEngineer();
4         cf.makeComputer(1,1);
5     }
6 }

 

  结果:

  技术分享

 

  CPU对象和主板对象需要相互匹配。在上面的实现中,CPU和主板是由客户任意选择的。例如,客户端调用makeComputer时,传入参数为(1,2),结果:

  技术分享

  客户选择的是Intel的CPU针脚数为755,选择的主板AMD上的CPU插孔是938,无法组装。

 

  引入抽象工厂模式

  抽象工厂模式与工厂方法模式的最大区别在于:工厂方法模式针对一个产品等级结构,而抽象工厂模式针对多个产品等级结构。

  产品族:在不同产品等级结构中功能相关联的产品组成的家族。例如,AMD的主板、芯片组、CPU组成一个家族,Intel的主板、芯片组、CPU组成一个家族。这两个家族都来自3个产品等级:主板、芯片组、CPU。一个等级结构是由相同结构的产品组成的,见下图:

  技术分享

  每一个产品族含有产品的数量与产品等级结构的数量相等。如果使用工厂方法模式,要使用3个独立的工厂等级结构来应对这3个产品等级结构。这3个产品等级结构的相似性会生成3个平行的工厂等级结构。随着产品等级结构的数量增加,工厂方法模式给出的工厂等级结构的数量也会增加,见下图:

  技术分享

  使用抽象工厂模式可以通过一个工厂等级结构来应对多个相同或相似的产品等级结构,见下图:

  技术分享

  一个工厂等级结构可以创建属于不同产品等级结构的一个产品族中的所有对象。抽象工厂模式比简单工厂模式、工厂方法模式更高效。每一个产品族都有一个具体工厂,而每一个具体工厂创建属于同一个产品族、不同等级结构的产品。

  

  抽象工厂模式结构

  抽象工厂模式可以处理具有相同(或者相似)等级结构中的多个产品族中的产品对象创建问题,见下图:

  技术分享

  工厂角色的结构设计图:

  技术分享

  每一个工厂角色都有两个工厂方法,分别创建属于不同产品等级结构的产品对象,见下图:

  技术分享

  前面实现的CPU接口和CPU接口实现类、主板接口和主板接口实现类不变。前面创建CPU的简单工厂和创建主板的简单工厂不需要了。

 

  新加入的抽象工厂类和实现类:

 1 public interface AbstractFactory {
 2     /**
 3      * 创建CPU对象
 4      * @return CPU对象
 5      */
 6     public Cpu createCpu();
 7     /**
 8      * 创建主板对象
 9      * @return 主板对象
10      */
11     public Mainboard createMainboard();
12 }

 

 1 public class IntelFactory implements AbstractFactory {
 2 
 3     @Override
 4     public Cpu createCpu() {
 5         // TODO Auto-generated method stub
 6         return new IntelCpu(755);
 7     }
 8 
 9     @Override
10     public Mainboard createMainboard() {
11         // TODO Auto-generated method stub
12         return new IntelMainboard(755);
13     }
14 
15 }

 

 1 public class AmdFactory implements AbstractFactory {
 2 
 3     @Override
 4     public Cpu createCpu() {
 5         // TODO Auto-generated method stub
 6         return new IntelCpu(938);
 7     }
 8 
 9     @Override
10     public Mainboard createMainboard() {
11         // TODO Auto-generated method stub
12         return new IntelMainboard(938);
13     }
14 
15 }

  装机工程师类变化:客户选的是一个产品族。将客户已选好的产品对象作为参数传入,避免了单独选择CPU和主板所带来的兼容性问题。

 1 public class ComputerEngineer {
 2     /**
 3      * 定义组装机需要的CPU
 4      */
 5     private Cpu cpu = null;
 6     /**
 7      * 定义组装机需要的主板
 8      */
 9     private Mainboard mainboard = null;
10     public void makeComputer(AbstractFactory af){
11         /**
12          * 组装机器的基本步骤
13          */
14         //1:首先准备好装机所需要的配件
15         prepareHardwares(af);
16         //2:组装机器
17         //3:测试机器
18         //4:交付客户
19     }
20     private void prepareHardwares(AbstractFactory af){
21         //这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
22         //可是,装机工程师并不知道如何去创建,怎么办呢?
23         
24         //直接找相应的工厂获取
25         this.cpu = af.createCpu();
26         this.mainboard = af.createMainboard();
27         
28         //测试配件是否好用
29         this.cpu.calculate();
30         this.mainboard.installCPU();
31     }
32 }

  客户端:

 1 public class Client {
 2     public static void main(String[]args){
 3         //创建装机工程师对象
 4         ComputerEngineer cf = new ComputerEngineer();
 5         //客户选择并创建需要使用的产品对象
 6         AbstractFactory af = new IntelFactory();
 7         //告诉装机工程师自己选择的产品,让装机工程师组装电脑
 8         cf.makeComputer(af);
 9     }
10 }

  

  抽象工厂定义了一个产品族,为一系列相关对象或相互依赖的对象创建一个接口。这个接口内的方法是一系列相关或相互依赖的方法。上面例子中的主板和CPU是组装一台电脑的相关对象。不同的装机方案表示一个产品族,见下图:

  技术分享

  通过提供不同的抽象工厂实现对象来切换产品族,见下图:

  技术分享

  

  抽象工厂模式适用场景:

  1 不依赖如何创建、组合和表达产品实例的细节(所有工厂模式均适用)。

  2 系统有多个产品族。

  3 强化属于同一个产品族的产品是在一起使用这一约束。例如,Intel主板必须使用Intel CPU、Intel芯片。

  4 系统提供的所有产品类实现了相同的接口,客户端不依赖于实现。

 

  抽象工厂模式的优点

  每一个产品类实现了同一个接口,使客户端不依赖于实现,有利于切换产品族。

 

  抽象工厂模式的缺点

  如果增加的产品族存在不同的行为,那么就需要修改抽象工厂类,从而需要修改所有的具体工厂实现类,不利于扩展。

  

  参考资料

  《JAVA与模式》之抽象工厂模式

以上是关于Java 设计模式 抽象工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

JAVA设计模式--抽象工厂模式

Java设计模式图文代码案例详解Java五大创建者模式 建造者原型(抽象)工厂单例模式

大话设计模式-抽象工厂模式(大鸟和小菜Java版)

抽象工厂模式(JAVA反射)

JAVA设计模式——抽象工厂模式案例实现

java抽象工厂的使用意图是啥?