一、模式的定义与特点
1. 抽象工厂模式
抽象工厂模式是工厂方法模式的进一步延伸,由于它提供了功能更为强大的工厂类并且具备较好的可扩展性,在软件开发中得以广泛应用,尤其是在一些框架和API类库的设计中,例如在Java语言的AWT(抽象窗口工具包)中就使用了抽象工厂模式,它使用抽象工厂模式来实现在不同的操作系统中应用程序呈现与所在操作系统一致的外观界面。抽象工厂模式也是在软件开发中最常用的设计模式之一。
抽象工厂(Abstract Factory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
使用抽象工厂模式一般要满足以下条件:
(1)系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
(2)系统一次只可能消费其中某一族产品,即同族的产品一起使用。
2.主要优点
抽象工厂模式的主要优点如下:
(1)抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
(2)当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
(3)增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
3.主要缺点
抽象工厂模式的主要缺点如下:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。
4.抽象工厂模式包含的角色:
(1)抽象工厂:声明一组用于创建一族产品的方法,每个方法对应一种对象。在抽象工厂中声明了多个工厂方法,用于创建不同类型的对象,抽象工厂可以是接口,也可以是抽象类或者具体类。
(2)具体工厂:具体工厂实现了抽象工厂,每个工厂方法返回一个具体对象,一个具体工厂所创建的具体对象构成一个族。
(3)抽象类接口:提供一组所有类都具有的业务方法。
(4)抽象类:用于实现抽象接口所定义的业务方法,但是该角色对于抽象接口定义的方法只做抽象实现,即所有实现都被定义为抽象方法,最终的具体实现全部交给具体类实现。引入该角色主要是为了根据声明不同的抽象类,将类区分为不同的等级结构。
(5)具体类:该角色继承抽象类,主要用于实现抽象类中声明的抽象方法,完成不同等级结构,不同族的业务方法的具体实现。
二、案例分析
假设现在有一个电脑制造工厂,配置性能一般和高性能两种不同性能级别的电脑,性能一般的电脑配置的是普通的CPU、RAM和显卡,而高性能的电脑配置的是高性能的CPU、RAM和显卡。由于抽象工厂的定义是为创建一组相关或者相互依赖的对象提供一个接口,而不需要指定它们的具体实现类,结合该情景,我们可以使用抽象工厂模式。
1.角色结构
(1)抽象工厂——ComputerFactory
声明配置电脑的方法:
package Factory; import interfaces.*; public abstract class ComputerFactory { //配置CPU public abstract CPU createCPU(); //配置内存 public abstract RAM createRAM(); //配置显卡 public abstract GC createGC(); }
(2)具体工厂
普通性能电脑具体生产工厂——NormalFactory
package Factory; import interfaces.*; import Class.*; public class NormalFactory extends ComputerFactory { @Override public CPU createCPU() { return new NormalCPU(); } @Override public RAM createRAM() { return new NormalRAM(); } @Override public GC createGC() { return new NormalGC(); } }
高性能电脑具体生产工厂——ExcellentFactor
package Factory; import interfaces.*; import Class.*; public class ExcellentFactory extends ComputerFactory { @Override public CPU createCPU() { return new ExcellentCPU(); } @Override public RAM createRAM() { return new ExcellentRAM(); } @Override public GC createGC() { return new ExcellentGC(); } }
(3)抽象类接口
CPU抽象接口
package interfaces; public interface CPU { public void cpu(); }
RAM抽象接口
package interfaces; public interface RAM { public void ram(); }
GC抽象接口
package interfaces; public interface GC { public void gc(); }
(4)抽象类
CPU接口实现类——普通性能
package Class; import interfaces.CPU; public class NormalCPU implements CPU { public void cpu(){ System.out.println("配置性能一般的CPU"); } }
CPU接口实现类——高性能
package Class; import interfaces.CPU; public class ExcellentCPU implements CPU { @Override public void cpu() { System.out.println("配置高性能的CPU"); } }
RAM接口实现类——普通性能
package Class; import interfaces.RAM; public class NormalRAM implements RAM { @Override public void ram() { System.out.println("配置性能一般的内存"); } }
RAM接口实现类——高性能
package Class; import interfaces.RAM; public class ExcellentRAM implements RAM { @Override public void ram() { System.out.println("配置高性能的内存"); } }
GC接口实现类——普通性能
package Class; import interfaces.GC; public class NormalGC implements GC { @Override public void gc() { System.out.println("配置性能一般的显卡"); } }
GC接口实现类——高性能
package Class; import interfaces.GC; public class ExcellentGC implements GC { @Override public void gc() { System.out.println("配置高性能的显卡"); } }
(5)具体类——Test
在客户端的具体实现:
import Factory.ComputerFactory; import Factory.ExcellentFactory; import Factory.NormalFactory; public class Test { public static void main(String[] args) { //构造一个生产一般电脑的工厂 ComputerFactory normal = new NormalFactory(); System.out.println("配置性能一般的电脑。。。"); normal.createCPU().cpu(); normal.createRAM().ram(); normal.createGC().gc(); System.out.println("\n-----这是一条分割线-----\n"); //构造一个生产高性能电脑的工厂 System.out.println("配置高性能的电脑。。。"); ComputerFactory excellent = new ExcellentFactory(); excellent.createCPU().cpu(); excellent.createRAM().ram(); excellent.createGC().gc(); } }
(6)输出结果
2.具体案例的UML图:
两个具体工厂类normalFactory和excellentFactory继承了抽象工厂ComputerFactory,并实现其相应的抽象方法,这样可以直接通过抽象工厂类来操作两个具体工厂类。抽象类实现了相应接口的方法,这样让具体工厂可以直接调用接口来使用抽象类中相应的方法。
3.总结
依据上述案例可以看出,通过抽象的工厂就可以实现高层次的复用,只需要知道实现类的类名就可以执行了,我们完全可以实现其他工厂,从而实现其他的功能。抽象工厂模式最重要的就是可复用性和隔离性,通过调用createXXX()来展现了这个方法的多态。抽象工厂将抽象零件组装成抽象产品,易于增加具体的工厂难于增加新的零件。
代码地址:https://github.com/Young0520/AbstractFactory