The simplest answer is to use require and eval-after-load as stated in other answers.
However that is not always convenient, such as in a function called by a mode hook that wants to activate another minor mode but only if the package for it is installed. In this case featurep is relevant.
Emacs packages increasingly use autoload to improve startup time. If you test for the presence of a package by using require then you are wearing the cost of loading the file(s). If using ELPA/MELPA/Marmalade packages (available by default since version 24) then many packages may be available in an as-yet unloaded state, but a package foo with autoloads will provide a feature foo-autoloads. I wrote a function that is useful for testing whether a package is available in terms of already being loaded or set to autoload.
(defun autofeaturep (feature)
"For a feature symbol 'foo, return a result equivalent to:
(or (featurep 'foo-autoloads) (featurep 'foo))
Does not support subfeatures."
(catch 'result
(let ((feature-name (symbol-name feature)))
(unless (string-match "-autoloads$" feature-name)
(let ((feature-autoloads (intern-soft (concat feature-name "-autoloads"))))
(when (and feature-autoloads (featurep feature-autoloads))
(throw 'result t))))
(featurep feature))))
(defun autofeaturep (feature)
"For a feature symbol 'foo, return a result equivalent to:
(or (featurep 'foo-autoloads) (featurep 'foo))
Does not support subfeatures."
(catch 'result
(let ((feature-name (symbol-name feature)))
(unless (string-match "-autoloads$" feature-name)
(let ((feature-autoloads (intern-soft (concat feature-name "-autoloads"))))
(when (and feature-autoloads (featurep feature-autoloads))
(throw 'result t))))
(featurep feature))))