Самое важное различие, и фактически определяющее различие между библиотекой и фреймворком, — это IoC (инверсия управления). Цитируя Мартина Фолвера в его статье об инверсии управления:
Инверсия управления — ключевая часть того, что отличает фреймворк от библиотеки. Библиотека — это, по сути, набор функций, которые вы можете вызывать, в наши дни обычно организованных в классы. Каждый вызов выполняет некоторую работу и возвращает управление клиенту. Фреймворк воплощает в себе некий абстрактный дизайн с большим количеством встроенного поведения. Чтобы использовать его, вам нужно вставить свое поведение в различные места в фреймворке либо путем создания подклассов, либо путем подключения ваших собственных классов. Код фреймворка затем вызывает ваш код в этих точках.
====================
Что это значит? Что ж, это означает, что когда вы вызываете библиотеку, вы контролируете ситуацию.
Но с фреймворком управление перевернуто: фреймворк зовет вас. (Голливудский принцип: не звоните нам, мы позвоним вам.) Это в значительной степени определение фреймворка. Если у него нет Inversion of Control, это не фреймворк.
===================
По сути, весь поток управления уже находится во фреймворке, и есть только куча предопределенных белых пятен, которые вы можете заполнить своим кодом. С другой стороны, библиотека — это набор функций, которые вы можете вызывать.
Еще одно хорошее объяснение можно найти в книге Gang of Four «Шаблоны проектирования, элементы многоразового объектно-ориентированного программного обеспечения», библии для каждого хорошего разработчика программного обеспечения. Вот определения Toolkit и Framework:
====================
Часто приложение включает классы из одной или нескольких библиотек предопределенных классов, называемых наборами инструментов. Инструментарий — это набор связанных и повторно используемых классов, предназначенных для обеспечения полезных функциональных возможностей общего назначения. Наборы инструментов не навязывают вашему приложению определенный дизайн; они просто предоставляют функциональные возможности, которые могут помочь вашему приложению выполнять свою работу. Они позволяют вам как разработчику избежать перекодирования общей функциональности. Наборы инструментов подчеркивают повторное использование кода.
====================
Фреймворк — это набор взаимодействующих классов, которые составляют повторно используемый дизайн для определенного класса программного обеспечения. Фреймворк определяет архитектуру вашего приложения. Он будет определять общую структуру, ее разбиение на классы и объекты, их ключевые обязанности, взаимодействие классов и объектов и поток управления.
=====================
Платформа предопределяет эти параметры проекта, чтобы вы, разработчик/разработчик приложения, могли сосредоточиться на специфике своего приложения. Платформа фиксирует проектные решения, которые являются общими для ее предметной области. Таким образом, фреймворки делают упор на повторное использование дизайна, а не на повторное использование кода, хотя фреймворк обычно включает конкретные подклассы, которые вы можете сразу же запустить в работу.
======================
Повторное использование на этом уровне приводит к инверсии контроля между приложением и программным обеспечением, на котором оно основано. Когда вы используете инструментарий (или, если уж на то пошло, обычную библиотеку подпрограмм), вы пишете основную часть приложения и вызываете код, который хотите использовать повторно. Когда вы используете фреймворк, вы повторно используете основное тело и пишете код, который он вызывает. Вам придется писать операции с определенными именами и соглашениями о вызовах, но это уменьшает количество проектных решений, которые вам придется принимать.
В результате вы не только можете быстрее создавать приложения, но и сами приложения имеют схожую структуру. Их легче поддерживать, и они кажутся пользователям более последовательными. С другой стороны, вы теряете некоторую творческую свободу, так как многие дизайнерские решения были приняты за вас.