Template Method Pattern in Dart: Cache Smarter Repositories

Three repositories, three copies of the same fetch-cache-fallback dance. The template method pattern in Dart fixes that with one base class that owns the algorithm skeleton while subclasses fill in the steps.

*Last updated: October 8, 2026* Every Flutter app with more than two data sources grows the same tumor: getProducts() , getOrders() and getProfile() each hand-roll their own cache check, network call, retry loop and stale-data fallback. The code works — until the cache policy needs to change in one place and you find it in seven files. The template method pattern dart repository caching approach exists for exactly this shape of duplication: an algorithm whose order of steps never changes, but whose individual steps differ per data source. In Dart, that becomes an abstract repository base class with one public method — the template — locking the fetch-cache-fallback skeleton in place. Subclasses only answer: "how do I fetch?" *Tested on Dart 3.13 (Flutter 3.47 stable, October 2026). All snippets run with dart run .* What you&#x27;ll build and learn A reusable CachedRepository<T> base class with a locked fetch → cache → fallback skeleton The difference between abstract steps (subclass must fill in) and hook methods (subclass may override) A Dart-specific gotcha: why the template method can&#x27;t be final , and what to do instead Concrete ProductRepository and OrderRepository subclasses with different TTLs and retry budgets A decision table: template method vs strategy vs decorator Four common mistakes that quietly break the pattern The copy-paste trap: fetch-cache-fallback written three times Here is what the duplication looks like before the pattern. Two repositories, same three steps, zero sharing: class ProductRepository { final Map<String, dynamic> _cache = {}; Future<Map<String, dynamic>> getProduct(String id) async { if (_cache.containsKey(id)) return _cache[id]!; // 1. cache check final data = await _api.fetch(&#x27;/products/$id&#x27;); // 2. fetch _cache[id] =…

Explore