想了一下,我决定还是做更细化的拆解,也看了很多源码剖析的文章1,以及我之前也写过,一个令人难受的点就是通篇的代码解释,通篇没什么头绪,我看着没头绪,感觉写的也没什么头绪,就是在硬看硬写,看完之后仍然不知云云,不得要领,无法复刻,写完之后的感觉也是。
在步入第三部分 接口&类的解析,我决定对每个一个接口&类的定义实现都进行拆解和剖析聊一聊这样设计的好处和原因2,并拆分为小块进行整理,以小见大。
最终应该会整理出一版最终的设计脉络。
ObjectPool 接口设计
ObjectPool 接口实际上是对整体的池化分配做了整体的抽象和解耦
通过定义两个接口 ObjectCreator 和 Handle 接口 将创建和回收解耦可以灵活提供各类实现。
整体的控制逻辑在 Recycler 中进行实现。
package io.netty.util.internal;
import io.netty.util.Recycler;
/**
* Light-weight object pool.
* T 的类型是要池化的资源的类型
* 对象池一般由 T 类持有,比如 PooledUnsafeDirectByteBuf 、 PooledDirectByteBuf
* 对应 T 类持有静态的对象池,可供直接分配调用 io.netty.buffer.PooledUnsafeDirectByteBuf#newInstance(int)
* @param <T> the type of the pooled object
*/
public abstract class ObjectPool<T> {
ObjectPool() { }
/**
* Get a {@link Object} from the {@link ObjectPool}. The returned {@link Object} may be created via
* {@link ObjectCreator#newObject(Handle)} if no pooled {@link Object} is ready to be reused.
* 获取一个 T 对象池中。
* 如果对象池中没有可重用的对象,这个返回的对象可能会通过 ObjectCreator#newObject 方法获取
*/
public abstract T get();
/**
* Handle for an pooled {@link Object} that will be used to notify the {@link ObjectPool} once it can
* reuse the pooled {@link Object} again.
* 用于表示池化的句柄 Handle , 用于通知对象池可以再次重用已经池化的对象
* @param <T>
*/
public interface Handle<T> {
/**
* Recycle the {@link Object} if possible and so make it ready to be reused.
* 回收方法,如果可能得话回收 T 对象自己,并使其准备好可以再次重用
* *
*/
void recycle(T self);
}
/**
* Creates a new Object which references the given {@link Handle} and calls {@link Handle#recycle(Object)} once
* it can be re-used.
* 创建一个新的对象,引用给的的 handle 并且在可以重新使用是调用 Handle 的 recycle 方法
* @param <T> the type of the pooled object
*/
public interface ObjectCreator<T> {
/**
* Creates an returns a new {@link Object} that can be used and later recycled via
* {@link Handle#recycle(Object)}.
* 创建一个新的可用对象返回, 可以通过 recycle 方法进行回收
*/
T newObject(Handle<T> handle);
}
/**
* Creates a new {@link ObjectPool} which will use the given {@link ObjectCreator} to create the {@link Object}
* that should be pooled.
* 创建一个新的对象池,并通过给定的 ObjectCreator 去创建应该被池化的对象
*/
public static <T> ObjectPool<T> newPool(final ObjectCreator<T> creator) {
return new RecyclerObjectPool<T>(ObjectUtil.checkNotNull(creator, "creator"));
}
/**
* 一个默认的对象池实现,持有一个 recycler 回收器,通过 recycler 执行对象获取
*/
private static final class RecyclerObjectPool<T> extends ObjectPool<T> {
private final Recycler<T> recycler;
RecyclerObjectPool(final ObjectCreator<T> creator) {
recycler = new Recycler<T>() {
@Override
protected T newObject(Handle<T> handle) {
return creator.newObject(handle);
}
};
}
@Override
public T get() {
return recycler.get();
}
}
}
这段代码涉及到对象池的设计,包括主要的接口 ObjectPool
以及与之关联的 Handle
和 ObjectCreator
接口。同时,通过内部的 RecyclerObjectPool
类实现了具体的对象池。
设计思路解析:
-
ObjectPool 接口: 该接口定义了对象池的基本操作,主要包括从池中获取对象的
get
方法。它是一个泛型接口,这使得它可以处理各种类型的对象。 -
Handle 接口: 这是一个用于处理池化对象的句柄接口,定义了回收对象的方法
recycle
。通过这个接口,实现了对象的回收与重用。 -
ObjectCreator 接口: 该接口定义了创建新对象的方法
newObject
,它接收一个Handle
对象,用于在创建对象时将其与对象池关联起来。这样,新创建的对象就能够被池化并通过Handle
进行回收。 -
RecyclerObjectPool 类: 这是
ObjectPool
接口的具体实现类,通过内部的Recycler
类来管理对象的创建和回收。将具体的对象创建逻辑放在Recycler
中的好处是可以实现更灵活的对象创建策略,例如通过对象池管理的对象进行初始化。 -
Recycler 类: 这是一个抽象类,实现了对象的创建和回收逻辑。通过继承该类,可以实现具体类型对象的创建和回收方法。将这部分逻辑抽象到
Recycler
中的好处是可以灵活地扩展和定制对象的创建和回收行为。
设计的好处和意义:
-
模块化和可扩展性: 将对象池的不同职责划分到不同的接口和类中,使得每个部分都可以单独扩展或替换,增强了系统的模块化和可扩展性。
-
解耦和复用: 将对象的创建、回收和池的管理分离,提高了代码的可维护性和复用性。例如,可以通过实现不同的
Recycler
子类来定制对象的创建和回收策略。 -
灵活性: 通过使用
ObjectCreator
和Handle
接口,使得对象的创建和回收可以被不同的实现灵活地处理,而不是硬编码在对象池中。 -
对于特定逻辑的集中处理: 将对象创建和回收逻辑放在
Recycler
类中,使得这些逻辑能够集中处理,有利于代码的维护和理解。同时,RecyclerObjectPool
作为具体的对象池实现类,主要负责管理Recycler
的使用,起到了组织和管理的作用。
总体来说,这种设计提供了更灵活、可扩展、可维护的对象池实现。大概……就是因为好拓展罢了,反正我觉得并不利于理解
可以预见的是这个系列估计要很长了…… ↩︎
其实也不见得是有什么好处,你想想你迭代的过程中,不是写的写的逻辑就成这样了,最后也能跑就懒得再优化,写框架的大牛也不见得所有设计都是 100% 优雅 ↩︎