本文通过简单数据库操作案例来说明抽象工厂模式的使用,使用Go语言和Java语言实现。
抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创
建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工
厂模式提供对象。
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品。
应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产
品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、
时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,但有利于说明抽象工
厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每
次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是
衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产
品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里
面加代码。
使用场景:1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项:产品族难扩展,产品等级易扩展。
适用性:
一个系统要独立于它的产品的创建、组合和表示时。
一个系统要由多个产品系列中的一个来配置时。
当你要强调一系列相关的产品对象的设计以便进行联合使用时。
当你提供一个产品类库,而只想显示它们是接口而不是实现时。
我们通过 sqlserver 和 access 两种数据库对用户表和部门表进行操作。
package factory
// 操作的用户表
type User struct {
Id int
Name string
}
package factory
// 用户表的操作
type IUser interface {
InsertUser(User) bool
GetUser(int)
}
package factory
import "fmt"
// SqlServer数据库操作用户表
type SqlServerUser struct {
}
func (sqlServerUser *SqlServerUser) InsertUser(user User) bool {
fmt.Println("SqlServer数据库插入用户!")
return true
}
func (sqlServerUser *SqlServerUser) GetUser(int) {
fmt.Println("SqlServer数据库查询用户!")
}
package factory
import "fmt"
// Access数据库操作用户表
type AccessUser struct {
}
func (accessUser *AccessUser) InsertUser(user User) bool {
fmt.Println("Access数据库插入用户!")
return true
}
func (accessUser *AccessUser) GetUser(int) {
fmt.Println("Access数据库查询用户!")
}
package factory
// 操作的部门表
type Deployment struct {
Id int
Name string
}
package factory
// 部门表的操作
type IDeployment interface {
InsertDeployment(Deployment) bool
GetDeployment(int)
}
package factory
import "fmt"
// SqlServer数据库操作部门表
type SqlServerDeployment struct {
}
func (sqlServerDeployment *SqlServerDeployment) InsertDeployment(deployment Deployment) bool {
fmt.Println("SqlServer数据库插入部门!")
return true
}
func (sqlServerDeployment *SqlServerDeployment) GetDeployment(int) {
fmt.Println("SqlServer数据库查询部门!")
}
package factory
import "fmt"
// Access数据库操作部门表
type AccessDeployment struct {
}
func (accessDeployment *AccessDeployment) InsertDeployment(deployment Deployment) bool {
fmt.Println("Access数据库插入部门!")
return true
}
func (accessDeployment *AccessDeployment) GetDeployment(int) {
fmt.Println("Access数据库查询部门!")
}
package factory
// 创建用户和部门操作的接口
type IFactory interface {
CreateUser() IUser
CreateDeployment() IDeployment
}
package factory
// Access数据库工厂
type AccessFactory struct {
}
func (accessFactory *AccessFactory) CreateUser() IUser {
return &AccessUser{}
}
func (accessFactory *AccessFactory) CreateDeployment() IDeployment {
return &AccessDeployment{}
}
package factory
// SqlServer数据库工厂
type SqlServerFactory struct {
}
func (sqlServerFactory *SqlServerFactory) CreateUser() IUser {
return &SqlServerUser{}
}
func (sqlServerFactory *SqlServerFactory) CreateDeployment() IDeployment {
return &SqlServerDeployment{}
}
package constant
const (
SqlServer = "sqlserver"
Access = "access"
)
package factory
import "proj/constant"
// 用一个简单工厂封装抽象工厂
type FactoryCreate struct {
}
func (factoryCreate *FactoryCreate) NewFactory(dbType string) IFactory {
switch dbType {
case constant.SqlServer:
return &SqlServerFactory{}
case constant.Access:
return &AccessFactory{}
}
return nil
}
package main
import (
"fmt"
"proj/constant"
. "proj/factory"
)
// 测试
func main() {
// 全局变量
var factory IFactory
var iUser IUser
var iDeployment IDeployment
// 操作用户
user := User{}
deployment := Deployment{}
// SqlServer操作
factory = &SqlServerFactory{}
iUser = factory.CreateUser()
iUser.InsertUser(user)
iUser.GetUser(1)
iDeployment = factory.CreateDeployment()
iDeployment.InsertDeployment(deployment)
iDeployment.GetDeployment(1)
// Access操作
factory = &AccessFactory{}
iUser = factory.CreateUser()
iUser.InsertUser(user)
iUser.GetUser(1)
iDeployment = factory.CreateDeployment()
iDeployment.InsertDeployment(deployment)
iDeployment.GetDeployment(1)
fmt.Println("========================")
// 简单工厂封装工厂方法
factoryCreate := FactoryCreate{}
// ==========SqlServer的工厂==========
factory = factoryCreate.NewFactory(constant.SqlServer)
iUser = factory.CreateUser()
iUser.InsertUser(user)
iUser.GetUser(1)
iDeployment = factory.CreateDeployment()
iDeployment.InsertDeployment(deployment)
iDeployment.GetDeployment(1)
// ==========Access的工厂==========
factory = factoryCreate.NewFactory(constant.Access)
iUser = factory.CreateUser()
iUser.InsertUser(user)
iUser.GetUser(1)
iDeployment = factory.CreateDeployment()
iDeployment.InsertDeployment(deployment)
iDeployment.GetDeployment(1)
}
# 程序输出
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
========================
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
package com.factory;
// 操作的用户表
public class User {
private int Id;
private String Name;
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
package com.factory;
// 用户表的操作
public interface IUser {
boolean InsertUser(User user);
void GetUser(int id);
}
package com.factory;
// SqlServer数据库操作用户表
public class SqlServerUser implements IUser {
@Override
public boolean InsertUser(User user) {
System.out.println("SqlServer数据库插入用户!");
return true;
}
@Override
public void GetUser(int id) {
System.out.println("SqlServer数据库查询用户!");
}
}
package com.factory;
// Access数据库操作用户表
public class AccessUser implements IUser {
@Override
public boolean InsertUser(User user) {
System.out.println("Access数据库插入用户!");
return true;
}
@Override
public void GetUser(int id) {
System.out.println("Access数据库查询用户!");
}
}
package com.factory;
// 操作的部门表
public class Deployment {
private int Id;
private String Name;
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
package com.factory;
// 部门表的操作
public interface IDeployment {
boolean InsertDeployment(Deployment deployment);
void GetDeployment(int id);
}
package com.factory;
// Access数据库操作部门表
public class AccessDeployment implements IDeployment {
@Override
public boolean InsertDeployment(Deployment deployment) {
System.out.println("Access数据库插入部门!");
return true;
}
@Override
public void GetDeployment(int id) {
System.out.println("Access数据库查询部门!");
}
}
package com.factory;
// SqlServer数据库操作部门表
public class SqlServerDeployment implements IDeployment {
@Override
public boolean InsertDeployment(Deployment deployment) {
System.out.println("SqlServer数据库插入部门!");
return true;
}
@Override
public void GetDeployment(int id) {
System.out.println("SqlServer数据库查询部门!");
}
}
package com.factory;
// 创建用户和部门操作的接口
public interface IFactory {
IUser CreateUser();
IDeployment CreateDeployment();
}
package com.factory;
// Access数据库工厂
public class AccessFactory implements IFactory {
@Override
public IUser CreateUser() {
return new AccessUser();
}
@Override
public IDeployment CreateDeployment() {
return new AccessDeployment();
}
}
package com.factory;
// SqlServer数据库工厂
public class SqlServerFactory implements IFactory {
@Override
public IUser CreateUser() {
return new SqlServerUser();
}
@Override
public IDeployment CreateDeployment() {
return new SqlServerDeployment();
}
}
package com.factory;
// 用一个简单工厂封装抽象工厂
public class FactoryCreate {
public IFactory NewFactory(DbType dbType) {
switch (dbType) {
case SQLSERVER:
return new SqlServerFactory();
case ACCESS:
return new AccessFactory();
}
return null;
}
}
package com.factory;
public class Test {
public static void main(String[] args) {
// 全局变量
IFactory factory = null;
IUser iUser = null;
IDeployment iDeployment = null;
// 操作用户
User user = new User();
Deployment deployment = new Deployment();
// SqlServer操作
factory = new SqlServerFactory();
iUser = factory.CreateUser();
iUser.InsertUser(user);
iUser.GetUser(1);
iDeployment = factory.CreateDeployment();
iDeployment.InsertDeployment(deployment);
iDeployment.GetDeployment(1);
// Access操作
factory = new AccessFactory();
iUser = factory.CreateUser();
iUser.InsertUser(user);
iUser.GetUser(1);
iDeployment = factory.CreateDeployment();
iDeployment.InsertDeployment(deployment);
iDeployment.GetDeployment(1);
System.out.println("========================");
// 简单工厂封装工厂方法
FactoryCreate factoryCreate = new FactoryCreate();
// ==========SqlServer的工厂==========
factory = factoryCreate.NewFactory(DbType.SQLSERVER);
iUser = factory.CreateUser();
iUser.InsertUser(user);
iUser.GetUser(1);
iDeployment = factory.CreateDeployment();
iDeployment.InsertDeployment(deployment);
iDeployment.GetDeployment(1);
// ==========Access的工厂==========
factory = factoryCreate.NewFactory(DbType.ACCESS);
iUser = factory.CreateUser();
iUser.InsertUser(user);
iUser.GetUser(1);
iDeployment = factory.CreateDeployment();
iDeployment.InsertDeployment(deployment);
iDeployment.GetDeployment(1);
}
}
# 程序输出
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
========================
SqlServer数据库插入用户!
SqlServer数据库查询用户!
SqlServer数据库插入部门!
SqlServer数据库查询部门!
Access数据库插入用户!
Access数据库查询用户!
Access数据库插入部门!
Access数据库查询部门!
一句话概括工厂模式:
简单工厂:一个工厂类,一个产品抽象类。
工厂方法:多个工厂类,一个产品抽象类。
抽象工厂:多个工厂类,多个产品抽象类。
生活中的工厂模式:
简单工厂类:一个麦当劳店,可以生产多种汉堡。
工厂方法类:一个麦当劳店,可以生产多种汉堡。一个肯德基店,也可以生产多种汉堡。
抽象工厂类:百胜餐饮集团下有肯德基和百事公司,肯德基生产汉堡,百事公司生成百事可乐。
区别:
简单工厂:只有唯一工厂(简单工厂),一个产品接口/抽象类,根据简单工厂中的静态方法来创建具体产品对
象,适用于产品较少,几乎不扩展的情景。简单工厂中的方法集中了所有产品创建的逻辑,一旦要拓展新产品
时,就不得不修改工厂类,并且会造成工厂的逻辑过于复杂,开发中很少使用。
工厂方法:有多个工厂(抽象工厂+多个具体工厂),一个产品接口/抽象类,根据继承抽象工厂中的方法来多态
创建具体产品对象,适用于一个类型的多个产品。工厂方法模式中,在新增一个新产品时,就要新增一个具体
工厂和一个具体产品类,这样程序的拓展性就有了提高,符合了开闭原则,避免了简单工厂模式的缺点,但是
新增产品时需要新增两个类,会增加代码量,可谓是有舍有得,具体如何要结合具体情况来使用,开发中经常
使用。
抽象方法:有多个工厂(抽象工厂+多个具体工厂),多个产品接口/抽象类,对产品子类进行分组,根据继承
抽象工厂中的方法多态创建同组的不同具体产品对象,适用于多个类型的多个产品。抽象工厂模式是所有工厂
模式的一般形式,当抽象工厂模式退化到只有一个产品等级结构时,就变成了工厂方法模式。当工厂方法模式
的工厂类只有一个时,且工厂方法为静态方法时,则又变成了简单工厂模式。与工厂方法模式相似,抽象工厂
模式隔离了具体类的生成,让客户端不清楚具体什么样的对象被创建。
抽象??模式与???法模式虽然主要意图都是为了解决接?选择问题,但在实现上抽象??是一个中???,创
建其他??的模式。