Обычно, под оптимизацией понимают:
1. Ускорение выполнения программы.
2. Уменьшение используемой памяти.
Пример: для работы с xml в джава модно использовать JAXP и SAX парсеры. SAX - однопроходный парсер, который не грузит xml файлы целиком в память, а предлагает использовать что-то вроде колбэков по определенным событиям (события: начало тэга, конец тэга, и т.д.). Таким образом он экономит память, но если нужно выполнить работу с DOM структурой xml файла, то sax парсеру придется проходить по документу несколько раз, что увеличивает время работы. По этой причине есть JAXP парсер, который сначала парсит xml документ целиком, строит для него DOM, но требует гораздо больше памяти, зато время работы существенно уменьшается. Как видно, оптимизация использования памяти/времени работы взаимосвязаны, потому перед оптимизацией стоит как можно больше узнать про нефункциональные требования к программе (Non functional requirements - NFRs), чтобы оптимизируя одно, не сломать другое.
Рефакторинг не подразумевает оптимизацию. Рефакторинг - , в первую очередь, это улучшение читабельности, поддерживаемости и расширяемости кода. Сферический пример в вакууме: вначале проекта решили напрямую инстанцировать объекты класса Bird, затем пришло осознание, что лучше использовать фабричный метод, т.к. для кое-где для тестов нужно использовать Dummy объекты. Затем решили перейти к фабрикам, потому что теперь наша система должна различать Duck и Goose. С нефункциональными требованиями эти изменения не связаны.