It is a relatively expensive operation to instantiate and destroy objects. To avoid many instantiations and destructions an ObjectPool is used which will reuse an already-created object. The ObjectPool class can pool both GameObjects and regular objects derived from System.object.
If you are wanting to create a new object, ObjectPool.Instantiate should be used instead of Instantiate. This function will create a new GameObject if one doesn't already exist within the pool. Similarly, to destroy an object, ObjectPool.Destroy should be used instead of Destroy. This will place the GameObject back in the pool.
In a similar way that GameObjects can be pooled, regular System.object objects can be pooled as well. To get a new object, ObjectPool.Get< T >() should be used. T specifies the type of object to get. For example, if you have a class named CustomClass you can get the pooled object with ObjectPool.Get< CustomClass >(). To return an object back to the pool ObjectPool.Return(obj) can be used.