1.什么是抽象工厂与工厂方法的区别联系
抽象工厂模式的定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。
对比一下工厂方法模式的定义:为某个对象提供一个接口,而且无需指定它们的具体类。
抽象工厂模式包括的角色:
(1)抽象产品类:为各种产品声明抽象接口或抽象类。
(2)具体产品类:抽象产品类的实现类,为实现某个具体产品的对象。
(3)抽象工厂类:声明了一组(注意是一组,看了下面的例子就会明白和工厂方法模式的区别)用于创建一种产品(每一个方法对应一种产品)的方法。
(4)具体工厂类:继承抽象工厂类,生成一组具体产品(注意是一组,这很重要)。
2.与工厂方法的区别
工厂方法模式:
(1)多个具体产品类都衍生自同一个接口或抽象类。
(2)一个抽象工厂类,可以派生出多个具体工厂类。
(3)并且每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
(1)多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。(不同点)
(2)一个抽象工厂类,可以派生出多个具体工厂类。(同工厂方法模式)
(3)并且每个具体工厂类可以创建多个具体产品类的实例。(不同点)
简单解释来讲
比如说鞋厂只能生产同一款鞋,而设想下一家代加工的鞋厂,里面可能既加工Adidas的鞋,同时还加工Nike的鞋,或者再想想,Nike和Adidas公司在生产鞋的同时,都还在生产衣服,那么,这种情况用工厂模式就不能做到了,因此产生了抽象工厂模式。
抽象工厂模式的适用范围比工厂模式更加广泛,它与工厂模式最大的区别在于:
工厂模式中一个工厂只能生产一种产品,而抽象工厂可以生产多个。
2.抽象工厂的使用场景
1.当一个系统要独立于他的产品创建,组合,和表示的时候时;
2.一个系统要由多个产品系列的中的一个来配置时候;
3.当你要强调一系列相关产品对象的设计以便来进行联合使用时候;
4.当你提供一个产品类库,而只想显示他们的接口而不是实现时候;
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项:产品族难扩展,产品等级易扩展。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
注意事项:产品族难扩展,产品等级易扩展。
白话文版本:
最大的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同产品配置。
2、它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
最典型的用法:
项目使用的是MySQL数据,现在如果需要更换为Oracle数据,为了灵活更换数据库,如何设计程序呢?
接下来通过抽象工厂模式模仿数据访问程序。
抽象工厂模式实现:
3.抽象工厂的用法
构建数据库表的对应类,只声明,不做任何操作。
User类:
为表创建相应的实现类:
IUser接口,用于客户端访问,解除与具体数据库访问的耦合:
MySQLUser类,用于访问MySQL的User表:
OracleUser类,用于访问Oracle的User表:
接下来再让我们构建一个IFactory接口,定义一个访问User表对象和Type对象的抽象的工厂接口
MySQLFactory类,实现IFactory接口,实例化MySQLUser
OracleFactory类,实现IFactory接口,实例化OracleUser
客户端代码
只需确认实例化哪一个数据库访问对象给factory。
运行结果如下:
只需要更改IFactory factory = new MySQLFactory() 为IFactory factory = new OracleFactory() ,就实现了数据库访问的切换了。
有一个User类和User操作类的时候,是只需要工厂方法模式,但是现在显然你数据中有很多的表,而MySQL和Oracle有时两大不同的分类,所以解决这种涉及到多个产品系列的问题,就需要抽象工厂模式了。
4.抽象工厂的类图
5.抽象工厂的优缺点:
优点:
易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
2、它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
缺点:
如果要增加一个项目表Project,那么就需要增加三个类,IProject,MySQLProject,OracleProject,还需要改动IFactory,MySQLFactory,OracleFactory才可以完全实现。这样是很糟糕的。
编程是门艺术,这样大批量的改动,显然是非常丑陋的做法。
解决方案:可以使用简单工厂来改进抽象工厂。去除IFactory、MySQLFactory、OracleFactory三个工厂类,用一个DataAcces类代替,用一个简单工厂模式来实现。具体实现代码省略,有兴趣的小伙伴可以自己实现。
6.抽象工厂与工厂模式代码级别对比
重构类图