立即学习:https://edu.csdn.net/course/play/28941/403597?utm_source=blogtoedu
抽象工厂模式(Abastract Factory Pattern)是指提供一个创建一些列相关获相互依赖对象的接口,无须指定他们具体的类。——属于创建型设计模式。
public interface IVideo{
void record();
}
public interface INote{
void edit();
}
public abstract class CourseFactory{
public void init(){
System.out,println("初始化基础数据");
}
protected abstract INote creatNote();
protected abstract IVideo creatVideo();
}
public class JavaVideo implements IVideo{
public void record(){
}
}
public class PythonVideo implements IVideo{
public void record(){
}
}
public class JavaNote implements INote{
public void edit(){
}
}
public class PythonNote implements INote{
public void edit(){
}
}
public class JavaCourseFactory extends CourseFactory{
protected INote createNote(){
super.init();
return new JavaNote();
}
protected IVideo createVideo(){
super.init();
return new JavaVideo();
}
}
public class PythonCourseFactory extends CourseFactory{
protected INote createNote(){
super.init();
return new PythonNote();
}
protected IVideo createVideo(){
super.init();
return new PythonVideo();
}
}
public class Test{
public static void main(String[] args){
CourseFactory factory = new JavaCourseFactory();
factory.createNote().edit();
factory.createVideo().record();
}
}
抽象工厂模式的适用场景
客户端(应用层)不依赖于产品类实例如何创建、实现细节。
强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。
提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
产品族:一系类的相关的产品,整合到一起有关联。
产品等级:同一个继承体系。
优点:
扫描二维码关注公众号,回复:
12428382 查看本文章

具体产品在应用层代码隔离,无须关心创建细节。
将一系类的产品族统一到一起创建。
缺点:
规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
增加了系统的抽象性和理解难度。
利用工厂模式重构的实践案例
JDBC操作案例,每次操作都需要重新创建数据库连接,每次创建其实都非常耗费性能,消耗业务调度时间。利用工厂模式,将数据库连接预先创建好放到容器中缓存着,在业务调用时就只需现取现用。
package jdbcfactory;
//Pool抽象类
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
import java.util.concurrent.locks.Condition;
/**
自定义连接池getInstance()返回Pool唯一实例,第一次调用时执行构造函数
构造函数Pool()调用驱动装载loadDrivers()函数;
连接池创建creatPool()函数loadDrivers()装载驱动;
createPool()建连接池getConnection()
返回一个连接实例getConnection(Long time)添加时间限制;
freeConne(connection con)将con连接实例返回当前使用的连接数
*/
public abstract class Pool {
public String propertiesName = "connection-INF.properties";
private static Pool instance = null; // 定义唯一实例
/**最大连接数*/
protected int maxConnect = 100;
/**保持连接数*/
protected int normalConnect = 10;
/**驱动字符串*/
protected String driverName = null;
/**驱动类*/
protected Driver driver = null;
/**私有构造函数,不允许外界访问*/
protected Pool(){
try{
init ();
loadDrivers(driverName);
}catch (Exception e){
e.printStackTrace();
}
}
/**初始化所有从配置文件中读取的成员变量*/
private void init() throws IOException {
InputStream is = Pool.class.getResourceAsStream(propertiesName);
Properties p = new Properties();
p.load(is);
this.driverName = p.getProperty("driverName");
this.maxConnect = Integer.parseInt(p.getProperty("maxConnect"));
this.normalConnect = Integer.parseInt(p.getProperty("normalConnect"));
}
/**装载和注册所有JDBC驱动程序
* @Param dri 接受驱动字符串*/
protected void loadDrivers(String dri) {
String driverClassName = dri;
try {
driver = (Driver) Class.forName(driverClassName).newInstance();
DriverManager.registerDriver(driver);
System.out.println("成功注册JDBC驱动程序" + driverClassName);
} catch (Exception e) {
System.out.println("无法注册JDBC驱动程序" + driverClassName + ",错误:" + e);
}
}
/**创建连接池*/
public abstract void createPool();
/**
* (单例模式)返回数据库连接池Pool实例
* @return
* @throws IOException
* @throws ClassCastException
* @throws IllegalAccessException
* @throws InterruptedException
* */
public static synchronized Pool getInstance() throws IOException,
ClassNotFoundException, IllegalAccessException, InstantiationException {
if (instance == null) {
instance.init();
instance = (Pool) Class.forName("org.e_book.sqlhelp.Pool").newInstance();
}
return instance;
}
/**获得一个可用连接,如果没有则创建一个连接,且小于最大连接限制
* @return*/
public abstract Connection getConnection();
/**获得一个连接,有时间限制
* @Param time 设置该链接持续时间(以毫秒为单位)*/
public abstract Connection getConnection(long time);
/**将连接对象返回给连接池
* @param con 获得连接对象*/
public abstract void freeConnection(Connection con);
/**返回当前空闲连接数*
* @return
*/
public abstract int getnum();
/**返回当前工作的连接数
* @return*/
public abstract int getnumActive();
/**关闭所有连接,撤销驱动注册(此方法为单例方法)*/
protected synchronized void release(){
// 撤销驱动
try {
DriverManager.deregisterDriver(driver);
System.out.println("撤销JDBC驱动程序 " + driver.getClass().getName());
} catch (SQLException e) {
System.out.println("无法撤销JDBC驱动程序的注册:"+driver.getClass().getName());;
}
}
}
package jdbcfactory;
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
import java.util.concurrent.locks.Condition;
import java.util.zip.CheckedOutputStream;
/**管理数据库连接池*/
public class DBConnectionPool extends Pool{
private int checkedOut; // 正在使用的连接数
/**存放产生的连接对象容器*/
private Vector<Connection> freeConnections = new Vector<>();
private String passWord = null; // 密码
private String url = null; // 连接字符串
private String userName = null; //用户名
private static int num = 0; //空闲连接数
private static int numActive = 0; // 当前可用的连接数
private static DBConnectionPool pool = null; // 连接池实例变量
/**产生数据连接池
* @return*/
public static synchronized DBConnectionPool getInstance(){
if (pool == null){
pool = new DBConnectionPool();
}
return pool;
}
/**
* 获得一个连接池实例*/
private DBConnectionPool(){
try {
init();
for (int i = 0; i < normalConnect; i++){
//初始化normalConn个连接
Connection c = newConnection();
if (c != null){
freeConnections.addElement(c);
num++;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
/**建立连接池*/
@Override
public void createPool() {
pool = new DBConnectionPool();
if (pool != null){
System.out.println("创建连接池成功");
}else {
System.out.println("创建连接池失败");
}
}
/**初始化
* @throws IOException*/
private void init() throws IOException {
InputStream is = DBConnectionPool.class.getResourceAsStream(propertiesName);
Properties p = new Properties();
p.load(is);
this.userName = p.getProperty("userName");
this.passWord = p.getProperty("passWord");
this.driverName = p.getProperty("driverName");
this.url = p.getProperty("url");
this.driverName = p.getProperty("driverName");
this.maxConnect = Integer.parseInt(p.getProperty("maxConnect"));
this.normalConnect = Integer.parseInt(p.getProperty("normalConnect"));
}
/**如果不再使用某个连接对象时,可调用此方法将该对象释放到连接池
* @param con*/
/**创建一个连接池
* @return*/
private Connection newConnection(){
Connection con = null;
try {
if (userName == null) {// 用户,密码都为空
con = DriverManager.getConnection(url);
} else {
con = DriverManager.getConnection(url, userName, passWord);
}
System.out.println("连接池创建一个新连接");
}catch (SQLException e) {
System.out.println("无法创建这个URL的连接"+url);
return null;
}
return con;
}
//(单利模式)获取一个可用连接
@Override
public synchronized Connection getConnection() {
Connection con = null;
if (freeConnections.size() > 0){ // 还有空的连接
num--;
con = (Connection) freeConnections.firstElement();
freeConnections.removeElementAt(0);
try{
if(con.isClosed()){
System.out.println("从连接池删除一个无效连接");
con = getConnection();
}
}catch (SQLException e){
System.out.println("从连接池删除一个无效连接");
con = getConnection();
}
}else if (maxConnect == 0 || checkedOut < maxConnect){ // 没有空闲连接且当前连接小于最大允许值,最大值为0则不限制
con = newConnection();
}
if (con != null){// 当前连接数+1
checkedOut++;
}
numActive++;
return con;
}
/**获取一个连接,并加上等待时间限制,时间为毫秒
* @param timeout 接受等待时间(以毫秒为单位)
* @return*/
@Override
public synchronized Connection getConnection(long timeout) {
long startTime = new Date().getTime();
Connection con;
while ((con = getConnection()) == null){
try {
wait(timeout); // 线程等待
}catch (InterruptedException e){
}
if ((new Date().getTime() - startTime) >= timeout){
return null;
}
}
return con;
}
/**关闭所有连接*/
public synchronized void release(){
try {
//将当前连接赋值到枚举中
Enumeration allConnections = freeConnections.elements();
//使用循环关闭所有连接
while (allConnections.hasMoreElements()){
//如果枚举对象至少还有一个可提供的元素,则返回次枚举的元素
Connection conn = (Connection) allConnections.nextElement();
try{
conn.close();
num--;
}catch (SQLException e){
System.out.println("无法关闭连接池中的连接");
}
}
freeConnections.removeAllElements();
numActive = 0;
}finally {
super.release();
}
}
/***/
@Override
public synchronized void freeConnection(Connection con) {
freeConnections.addElement(con);
num++;
checkedOut--;
numActive--;
notifyAll();//解锁
}
@Override
public int getnum() {
return num;
}
@Override
public int getnumActive() {
return numActive;
}
}