介绍
将创建对象的具体过程屏蔽、隔离,从而达到更高的灵活性,工厂模式可以分为:简单工厂模式【Simple Factory】、工厂方法模式【Factory Method】、抽象工厂模式【Abstract Factory】;
简单工厂模式
定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可;
UML结构图
- 工厂类角色:该模式的核心,用来创建产品,含有一定的商业逻辑和判断逻辑;
- 抽象类产品角色:它一般是具体产品继承的父类或者实现的接口;
- 具体产品角色:工厂类所创建的对象就是此角色的实例,在Java中由一个具体类实现。
代码实现
产品类:
abstract class BMW {public BMW(){}}public class BMW320 extends BMW {public BMW320() {System.out.println("制造-->BMW320");}}public class BMW523 extends BMW{public BMW523(){System.out.println("制造-->BMW523");}}
工厂类:
public class Factory {public BMW createBMW(int type) {switch (type) {case 320:return new BMW320();case 523:return new BMW523();default:break;}return null;}}
客户端:
public class Customer {public static void main(String[] args) {Factory factory = new Factory();BMW bmw320 = factory.createBMW(320);BMW bmw523 = factory.createBMW(523);}}
优缺点
优点:提供工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需要知道所创建的具体产品类类名以及创建过程,只需要知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性;
缺点:不符合开闭原则,每次添加新产品就修改修改工厂类。在产品类型较多时,会造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作就会影响整个系统。
工厂方法模式
将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。
UML结构图
- 抽象工厂AbstrectFactory:工厂方法模式的核心,是具体工厂角色必须实现的接口或者必须继承的父类,在Java中由抽象类或者接口来实现;
- 具体工厂Factory:被应用程序调用以创建具体产品的对象,含有具体业务逻辑相关的代码;
- 抽象产品AbstractProduct:具体产品继承的父类或实现的接口,在Java中一般由抽象类或者是接口来实现;
- 具体产品Product:具体工厂角色所创建的对象。
代码实现
产品类:
abstract class BMW {public BMW(){}}public class BMW320 extends BMW {public BMW320() {System.out.println("制造-->BMW320");}}public class BMW523 extends BMW{public BMW523(){System.out.println("制造-->BMW523");}}
工厂类:
interface FactoryBMW {BMW createBMW();}public class FactoryBMW320 implements FactoryBMW{@Overridepublic BMW320 createBMW() {return new BMW320();}}public class FactoryBMW523 implements FactoryBMW {@Overridepublic BMW523 createBMW() {return new BMW523();}}
客户类:
public class Customer {public static void main(String[] args) {FactoryBMW320 factoryBMW320 = new FactoryBMW320();BMW320 bmw320 = factoryBMW320.createBMW();FactoryBMW523 factoryBMW523 = new FactoryBMW523();BMW523 bmw523 = factoryBMW523.createBMW();}}
抽象工厂模式
产品等级结构:产品等级结构指的是产品的继承结构,例如一个空调抽象类,有海尔空调、格力空调、美的空调等一系列子类,在这个空调抽象类和他的子类就构成一个产品等级结构;
产品足:产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如海尔工厂生产海尔空调、海尔冰箱,它们都来自不同 产品等级。
抽象工厂模式的定义
主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
但是在添加新的行为时比较麻烦,如果需要添加一个新产品族对象,需要变更接口以及旗下的所有子类,比较麻烦。
UML结构图:
- AbstractFactory:抽象工厂,提供创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品,里面包含所有产品创建的抽象方法;
- ConcreteFactory:具体工厂,实现抽象工厂中的多个抽象方法,完成具体产品的创建;
- Product:抽象产品,定义产品的规范,描述产品的主要特性和功能,完成具体产品的创建,可能会有两种不同的实现;
- ConcreteProduct:具体的产品,主要实现抽象产品所定义的接口,由具体工厂来创建,同具体工厂之间是多对一的关系。
代码实现:使用不同的数据库【mysql、sqlserver】,对不同的数据表【user表、department表】进行数据的插入和获取;
- IFactory:抽象工厂,定义出创建具体产品的抽象产品;
- SqlServerFactory:具体工厂,定义创建使用SqlServer的user和department产品;
- MysqlFactory:具体工厂,定义创建使用Mysql的user和department产品;
- IUser:抽象user产品,定义user相关的操作和特性;
- SqlServerUser:SqlServer的user产品;
- MySqlUser:MySql的user产品;
- IDepartment:抽象department产品,定义department相关特性以及方法;
- SqlServerDepartment:SqlServer的department产品;
- MySqlDepartment:Mysql的department产品;
抽象工厂:
/*** @author xulihua* @date 2021/1/18 11:10* 抽象工厂*/public interface IFactory {/*** 创建user* @return*/IUser createUser();/*** 创建department* @return*/IDepartment createDepartment();
mysql工厂:
/*** @author xulihua* @date 2021/1/18 11:20* mysql工厂*/public class MySqlFactory implements IFactory {@Overridepublic IUser createUser() {return new MySqlUser();}@Overridepublic IDepartment createDepartment() {return new MySqlDepartment();}}
SqlServer工厂:
/*** @author xulihua* @date 2021/1/18 11:18* sqlserver工厂*/public class SqlServerFactory implements IFactory {@Overridepublic IUser createUser() {return new SqlServerUser();}@Overridepublic IDepartment createDepartment() {return new SqlServerDepartment();}}
抽象产品User:
/*** @author xulihua* @date 2021/1/18 11:13* 抽象产品user*/public interface IUser {/*** 插入数据* @param user*/void insert(User user);/*** 获取数据* @param id* @return*/User getOne(Integer id);}
抽象产品Department:
/*** @author xulihua* @date 2021/1/18 11:14* 抽象产品department*/public interface IDepartment {/*** 插入数据* @param department*/void insert(Department department);/*** 获取数据* @param id* @return*/Department getOne(Integer id);}
具体产品mysql族的User
/*** @author xulihua* @date 2021/1/18 11:56* 具体user产品[mysql]*/public class MySqlUser implements IUser {@Overridepublic void insert(User user) {Common.addUser(user);System.out.println("MySql添加user数据:"+user);}@Overridepublic User getOne(Integer id) {User user = Common.getUser(id);System.out.println("MySql获取id为"+id+"user数据:"+user);return user;}}
具体产品SqlServer的User
/*** @author xulihua* @date 2021/1/18 11:20* 具体产品user[SqlServer]*/public class SqlServerUser implements IUser{@Overridepublic void insert(User user) {Common.addUser(user);System.out.println("插入user数据:"+user);}@Overridepublic User getOne(Integer id) {User user = Common.getUser(id);System.out.println("获取id为"+id+"的user记录:"+user);return user;}}
具体产品mysql族的department
/**
* @author xulihua
* @date 2021/1/18 11:58
* 具体产品department[mysql]
*/
public class MySqlDepartment implements IDepartment {
@Override
public void insert(Department department) {
Common.addDepartment(department);
System.out.println("MySQL添加department数据"+department);
}
@Override
public Department getOne(Integer id) {
Department department = Common.getDepartment(id);
System.out.println("MySQL获取id为"+id+"的department数据:"+department);
return department;
}
}
具体产品SqlServer的department
/**
* @author xulihua
* @date 2021/1/18 11:40
* 具体产品department[SqlServer]
*/
public class SqlServerDepartment implements IDepartment{
@Override
public void insert(Department department) {
Common.addDepartment(department);
System.out.println("SqlServer添加department数据:"+department);
}
@Override
public Department getOne(Integer id) {
Department department = Common.getDepartment(id);
System.out.println("SqlServer获取id为"+id+"department数据:"+department);
return department;
}
}
客户端
/**
* @author xulihua
* @date 2021/1/18 12:04
*/
public class Client {
public static void main(String[] args) {
// mysql
IFactory factory=new MySqlFactory();
IUser user = factory.createUser();
User u1= new User(44,"虎虎");
user.insert(u1);
user.getOne(44);
// SqlServer
// SqlServerFactory sqlServerFactory = new SqlServerFactory();
// IDepartment department = sqlServerFactory.createDepartment();
// Department dep = new Department(55, "技术部");
// department.insert(dep);
// department.getOne(55);
}
}
工厂模式小结:
区别:
工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例;
抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例。
