为什么要有工厂模式?
我们在学习一个东西之前,应该要先了解下他为什么出现,他解决了什么问题。这样才可以带着思考的高效学习。
以数据库为例,我们知道常见的关系型数据库有mysql、sqlserver、oracle等,每种数据库连接实例的创建都是复杂且易错麻烦的。如果将这些连接实例交给用户来创建,是十分不合适的。我们就希望有一个类帮我负责这些不同数据库实例的创建。我们只需要告诉它我们需要哪个数据库实例,以及一些参数(数据库名称,密码等),它来创建好然后提供给我们。这样不但可以减少代码冗余,也可以降低代码的耦合度。
简单工厂
以刚刚数据库为例子,我们尝试写一个简单的工厂类。那我们首先需要先提供下三种数据库连接类(真正的连接是很复杂的,这里简单写)。
第一步:先写个数据库连接的抽象类(水平有限,先这样写)。
假设有prepare()和finish()两个方法,他们的作用就是完成复杂的对象创建工作,由工厂对象进行调用,所以将他们访问级别设置为默认(我将工厂类和数据库类放在了一个包下)。
query()方法假设是数据库可以进行的操作,工厂创建完实例后提供给用户使用的,所以是public的。
getDatabaseName()方法留给子类重写。
package study.factory.simple;
/**
* @author 阿呆的小鸡仔
*/
public abstract class Database {
/**
* 连接用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 端口
*/
private Integer port;
Database(String username, String password, Integer port) {
this.username = username;
this.password = password;
this.port = port;
}
/**
* 设置数据库名称
* @return 数据库的名称
*/
protected abstract String getDatabaseName();
/**
* 创建数据库连接实例需要的操作,每种数据库应该都是不一样的
*/
void prepare(){
System.out.println("开始准备进行 "+this.getDatabaseName()+" 需要的初始化步骤");
System.out.println("验证密码 "+this.password+" 是否正确......");
System.out.println("各种初始化操作=======");
}
/**
* 创建连接完成时的操作
*/
void finish(){
System.out.println("用户:"+this.username
+" \n已经成功连接至"+this.getDatabaseName()
+"\n端口:"+this.port
);
}
/**
* 假设这个是实例的功能,可以用来执行查询语句
* @param query 查询语句
*/
public abstract void query(String query);
}
第二步:写一下Mysql类和SqlServer类
package study.factory.simple;
/**
* @author 阿呆的小鸡仔
*/
public class Mysql extends Database {
Mysql(String username, String password, Integer port) {
super(username, password, port);
}
@Override
public String getDatabaseName() {
return "MySQL数据库";
}
@Override
public void query(String query) {
System.out.println(getDatabaseName()+"执行了:"+query);
}
}
这里重写下SqlServer的prepare(),区别下mysql与sqlserver的准备工作是不一样。
package study.factory.simple;
/**
* @author 阿呆的小鸡仔
*/
public class SqlServer extends Database {
SqlServer(String username, String password, Integer port) {
super(username, password, port);
}
@Override
public String getDatabaseName() {
return "SQLServer数据库";
}
@Override
void prepare() {
System.out.println(getDatabaseName()+" 初始化完成");
}
@Override
public void query(String query) {
System.out.println(getDatabaseName()+"执行了:"+query);
}
}
第三步:写我们的简单工厂类
package study.factory.simple;
/**
* @author 阿呆的小鸡仔
*/
public class SimpleFactory {
/**
* 用来创建我们所需要的数据库实例
* @param type 数据库类型
* @param username 用户名
* @param password 密码
* @param port 端口
* @return 数据库实例
*/
public static Database createDatabase(DatabaseType type,String username,String password,Integer port){
Database database=null;
if(DatabaseType.MYSQL==type){
/*现实中可能是十分复杂的*/
database=new Mysql(username,password,port);
database.prepare();
database.finish();
}
if(DatabaseType.SQLSERVER==type){
database=new SqlServer(username,password,port);
database.prepare();
database.finish();
}
return database;
}
public enum DatabaseType{
/**
* mysql
*/
MYSQL,
/**
* sqlserver
*/
SQLSERVER;
}
}
第四步:写个测试类,试试使用我们的工厂类来创建对象。
/**
* @author 阿呆的小鸡仔
*/
public class Main {
public static void main(String[] args) {
Database mysql = SimpleFactory.createDatabase(SimpleFactory.DatabaseType.MYSQL, "zjj", "123456", 80);
mysql.query("select * from user");
mysql=SimpleFactory.createDatabase(SimpleFactory.DatabaseType.SQLSERVER,"zjj", "123456", 80);
mysql.query("select * from role");
}
}