Flutter Design Patterns: Abstract Factory ( Flutter Tasarım Kalıpları: Soyut Fabrika )

IT for your business

d59a3b3e 55be 4ae4 90c9 78eda76eadee

Abstract Factory, ilgili veya bağımlı nesnelerin sınıflarını belirtmeden ailelerini oluşturan bir arayüz sağlayan bir yaratıcı tasarım deseni’dir.

Dart ve Flutter’da, Abstract Factory modeli, farklı nesnelerin oluşturulması için fabrika için bir soyut sınıf oluşturularak ve metodlar yazılarak uygulanabilir.

Abstract Factory tasarım kalıbı, sınıflarını belirtmeden ilgili nesnelerin ailelerini oluşturma yolunu sunar. Bu, daha büyük esneklik ve özelleştirme imkanı sağlar.

Abstract Factory tasarım şablonu nedir?

Abstract Factory, Kit olarak da bilinen bir yaratıcı tasarım şablonudur. GoF kitabındaki amacı, belirli sınıfları belirtmeden aileleri ile ilgili veya bağımlı nesnelerin oluşturulması için bir arayüz sunmaktır. Abstract Factory tasarım şablonunun ana amacı, nesnelerin oluşturma işlemini ayrı bir fabrika nesnesi içinde saklamak ve nesne oluşturma işlemini soyutlamaktır. Desteklenen tüm nesne aileleri için, bir nesne ailesinin oluşturulması için ortak bir arayüz tanımlanır ve daha sonra bu arayüzü uygulamak için bir concreate fabrika sınıfı oluşturulur.

Abstract Factory tasarım deseni, concrete sınıflarını belirtmeden ilgili veya bağımlı nesnelerin ailelerinin oluşturulmasına olanak tanıyan bir yaratıcı tasarım desenidir. Bu desenin ana amacı, nesne oluşumunu ayrı bir fabrika nesnesi içinde kapsüllemeyi ve aile içindeki nesne oluşumunu ortak bir arayüz sağlamayı içermektir.

Abstract Factory ve Factory Method tasarım desenleri arasındaki ana fark, ilk olanın ilişkili nesnelerin bir grubunu oluşturma yolunu sunması iken, diğerinin tek bir belirli nesne oluşturma odaklı olduğudur.

Abstract Factory tasarım deseni derleme zamanı ve çalışma zamanı esnekliği sunar. Yeni alt sınıfların tanımlanması ile müşterilerden bağımsız olarak nesne oluşumunun uygulanması ve değiştirilmesine olanak tanır. Ayrıca, sınıfların fabrika nesnesi ile yapılandırılmasına ve hatta dinamik olarak değiştirilmesine olanak tanır. Bu desen, uygulama spesifik sınıfların doğrudan bağlantısını kaldırarak, kodun belirli nesnelerin arayüzleri ve onların fabrikaları ile ilgilenmesine, spesifik uygulamalarla değil, imkan tanır.

Abstract Factory’nin ayrıntılarını ve nasıl uygulanabileceğini anlamak için, deseni analiz etmek önemlidir.

Analiz

Abstract Factory tasarım deseninin analizi, bu desenin nasıl uygulanacağını, faydalarını ve sınırlamalarını anlamaya yardımcı olur.

img 0260
Flutter Design Patterns: Abstract Factory ( Flutter Tasarım Kalıpları: Soyut Fabrika ) 4

Analiz aşamaları şunları içerebilir:

  1. Sınıf ve nesne yapısının belirlenmesi: Abstract Factory deseninde hangi sınıfların ve nesnelerin kullanılacağının belirlenmesi gerekir.
  2. İlişkilerin tanımlanması: Abstract Factory deseninde, sınıflar arasındaki ilişkilerin tanımlanması gerekir.
  3. Fabrika arayüzünün tanımlanması: Fabrika arayüzü, aile içindeki nesnelerin oluşturulması için ortak bir yol sağlar.
  4. Fabrika sınıflarının tanımlanması: Fabrika arayüzünü uygulayan fabrika sınıfları tanımlanır.
  5. Uygulamanın test edilmesi: Abstract Factory deseni uygulandıktan sonra, uygulamanın doğru çalışıp çalışmadığını test etmek gerekir.

Bu aşamaların tamamlanması ile Abstract Factory tasarım deseni uygulanmış olur ve belirli amaçlar için nesnelerin oluşumu daha esnek ve kontrollü hale gelir.

uygulanabilirlik

Abstract Factory tasarım deseni, birçok farklı senaryoda uygulanabilir. Örneğin, aşağıdaki durumlarda kullanılabilir:

  1. Aile içindeki nesnelerin oluşumunun düzenlenmesi: Abstract Factory, aile içindeki nesnelerin oluşumunu düzenlemek ve bunları tek bir yerden yönetmek için kullanılabilir.
  2. Uygulama içinde farklı platformlar ve işletim sistemleri desteği: Abstract Factory, uygulamanın farklı platformlar ve işletim sistemleri desteği sunması için kullanılabilir.
  3. Esnek ve değişebilir nesne yapısı: Abstract Factory, esnek ve değişebilir nesne yapısı sunması için kullanılabilir.
  4. İlişkisel nesnelerin oluşumunun kolaylaştırılması: Abstract Factory, ilişkisel nesnelerin oluşumunu kolaylaştırmak için kullanılabilir.

Bu örnekler sadece bir başlangıç noktasıdır ve Abstract Factory tasarım deseni farklı senaryolarda da uygulanabilir. Anahtar faktör, nesnelerin oluşumunun düzenlenmesi ve kontrol edilmesi gereksinimidir.

uygulanması

Abstract Factory tasarım deseni aşağıdaki adımlarla uygulanabilir:

  1. Aile içindeki nesnelerin oluşturulması için ortak bir arayüz tanımla: İlk adım, fabrika sınıfının nesneleri aile içinde oluşturmak için kullanacağı ortak bir arayüz tanımlamaktır.
  2. Somut fabrika sınıfları oluştur: Arayüz tanımlandıktan sonra, aile içindeki nesneleri oluşturacak olan somut fabrika sınıflarını oluşturun. Her somut fabrika sınıfı, aile içindeki belirli bir tür nesnenin oluşturulmasından sorumlu olmalıdır.
  3. Müşteri sınıfını tanımla: Müşteri sınıfı, fabrika kullanarak nesneleri oluşturan sınıftır. Fabrika nesnesine bir referans içermelidir ve aile içindeki nesneleri oluşturmak için kullanılmalıdır.
  4. Müşteri sınıfını kullan: Abstract Factory tasarım desenini kullanmak için, müşteri sınıfının bir örneğini oluşturun, fabrika nesnesini ayarlayın ve aile içindeki nesneleri oluşturmak için uygun metodu çağırın.
  5. Kodu değiştir: Gerektiğinde, aile içindeki ek nesneler desteklemek veya farklı somut fabrikalar kullanmak için kodu değiştirin.

Önemli bir nokta, Abstract Factory tasarım deseni sınıf tabanlı yaklaşım veya nesne tabanlı yaklaşım kullanılarak uygulanabilir. Sınıf tabanlı yaklaşım fabrikayı uygulamak için sınıf kalıtımı kullanır, nesne tabanlı yaklaşım ise nesne bileşimini kullanır.

Flutter kullanarak aynı kod tabanını kullanmanıza rağmen, genellikle UI bileşenlerinin farklı platformlarda farklı görünmesi gerektiği bir talebiniz olacaktır. Flutter kontekstinde hayal edilebilen en basit kullanım durumu - Material veya Cupertino stilinde widget’ların gösterilmesi, sırasıyla Android veya iOS cihazı kullanıyor olup olmadığınıza göre.

Son kez, kodumuza Fabrika Metodu desenini ekleyerek ve her platforma özgü bileşen için gerekli widget’ı dinamik olarak oluşturan ve işlem seviyesini (UI) temsile ayrılan ayrı bir fabrika sağlayarak bu sorunu çözdük. Ancak, birden fazla bileşenin farklı platformlarda farklı görünmesi gereken durumlar için bu yaklaşım, her yeni bileşen için ayrı bir soyut sınıf ve her spesifik platform için uygulamanın yapılması için 3 ek türetilmiş sınıf eklemeniz gerektiğinden büyük bir baş ağrısı halini alır.

Bu problemler aklımızda bulununca, Fabrika Metodu deseni yerine Abstract Factory tasarım deseni, her platform için tek bir fabrika gerektiğinden, bir bileşen ailesinin birlikte oluşturulması ve kullanılması için daha iyi bir seçimdir.

Class diagram

Class diagram, yazılım tasarımı veya modelleme için kullanılan bir notasyon yöntemidir. Sınıflar, nesnelerin tasarımını tanımlayan ve nesne tabanlı programlamada kullanılan öğeleri temsil eder. Class diagramları, sınıflar arasındaki ilişkileri (örneğin kalıtım, çoklu kalıtım veya bağlantı), sınıf özelliklerini (örneğin veri alanları ve metodları) ve sınıflar arasındaki mesajlaşmayı (örneğin, nesne bir başka nesnenin bir metodunu çağırabilir) görsel olarak görselleştirir.

Aşağıdaki sınıf diyagramı, Abstract Factory tasarım deseninin uygulamasını gösterir.

img 0261
Flutter Design Patterns: Abstract Factory ( Flutter Tasarım Kalıpları: Soyut Fabrika ) 5

Sınıf Diyagramı – Abstract Factory tasarım deseninin uygulaması

IWidgetsFactory, tüm belirli araç fabrikaları için arayüz olarak kullanılan soyut bir sınadır:

getTitle() – arayüzün başlığını döndüren soyut bir yöntem. Kullanımı UI’dedir; createActivityIndicator() – IActivityIndicator arayüzünü uygulayan aktivite (süreç) göstergesinin belirli uygulamasını (UI bileşeni / araç) döndüren soyut bir yöntem; createSlider() – ISlider arayüzünü uygulayan slaytın belirli uygulamasını (UI bileşeni / araç) döndüren soyut bir yöntem; createSwitch() – ISwitch arayüzünü uygulayan anahtar düğmesinin belirli uygulamasını (UI bileşeni / araç) döndüren soyut bir yöntemdir. MaterialWidgetsFactory ve CupertinoWidgetsFactory, IWidgetsFactory sınıfını ve yöntemlerini uygulayan somut sınıflardır. MaterialWidgetsFactory, Material stili bileşenler (araçlar) oluştururken, CupertinoWidgetsFactory, Cupertino stili araçlar oluşturur.

IActivityIndicator, ISlider ve ISwitch, her bileşen için render() yöntemini tanımlayan soyut sınıflardır. Bu sınıflar hem Material hem de Cupertino tarafından uygulanır.

AndroidActivityIndicator, AndroidSlider ve AndroidSwitch, Material araçlarının render() yöntemini uygulayan somut uygulamalarıdır.

IosActivityIndicator, IosSlider ve IosSwitch, Cupertino araçlarının render() yöntemini uygulayan somut uygulamalarıdır.

AbstractFactoryExample, IWidgetsFactory arayüzünü uygulayan bir liste fabrika içerir. Belirli bir fabrikayı seçtikten sonra örnek araç, karşılık gelen araçları / UI bileşenlerini oluşturmak için fabrikanın yöntemlerini kullanır.

IWidgetsFactory

Bir arayüz, belirli fabrika sınıfları tarafından uygulanması gereken metodları tanımlar. Bu metodlar, beton fabrika tarafından tanımlanmış belirli türde bileşenler (widget’lar) oluşturmak için kullanılır. Dart dilinde arayüz sınıf tipi olarak desteklenmez, bu nedenle bir arayüzü bir soyut sınıf oluşturarak ve varsayılan uygulama olmadan bir metod başlığı (isim, dönüş tipi, parametreler) sağlayarak tanımlarız.

Evet, burada size bir Flutter içinde IWidgetsFactory adında bir arayüz tanımı ve onun nasıl uygulanabileceğine dair bir örnek kod veriyorum:

abstract class IWidgetsFactory {
  Widget createButton(String text);
  Widget createTextField(String hintText);
}

class MaterialWidgetsFactory implements IWidgetsFactory {
  @override
  Widget createButton(String text) {
    return RaisedButton(
      onPressed: () {},
      child: Text(text),
    );
  }

  @override
  Widget createTextField(String hintText) {
    return TextField(
      decoration: InputDecoration(hintText: hintText),
    );
  }
}

class CupertinoWidgetsFactory implements IWidgetsFactory {
  @override
  Widget createButton(String text) {
    return CupertinoButton(
      onPressed: () {},
      child: Text(text),
    );
  }

  @override
  Widget createTextField(String hintText) {
    return CupertinoTextField(
      placeholder: hintText,
    );
  }
}

Bu örnekte, IWidgetsFactory arayüzü createButton ve createTextField adında iki metod tanımlar. MaterialWidgetsFactory ve CupertinoWidgetsFactory sınıfları bu arayüzü uygular ve her biri farklı türde Widget‘lar oluşturmak için bu metodların uygulamalarını sağlar.

Widget fabrikaları

MaterialWidgetsFactory – IWidgetsFactory arayüzünü ve Material stilli widget’lar oluşturmak için metodlarını uygulayan, beton fabrika sınıfıdır.

Evet, size bir örnek kod veriyorum:

abstract class IWidgetsFactory {
  Widget createButton(String text);
  Widget createTextField(String hintText);
}

class MaterialWidgetsFactory implements IWidgetsFactory {
  @override
  Widget createButton(String text) {
    return RaisedButton(
      onPressed: () {},
      child: Text(text),
    );
  }

  @override
  Widget createTextField(String hintText) {
    return TextField(
      decoration: InputDecoration(hintText: hintText),
    );
  }
}

class CupertinoWidgetsFactory implements IWidgetsFactory {
  @override
  Widget createButton(String text) {
    return CupertinoButton(
      onPressed: () {},
      child: Text(text),
    );
  }

  @override
  Widget createTextField(String hintText) {
    return CupertinoTextField(
      placeholder: hintText,
    );
  }
}

void main() {
  IWidgetsFactory widgetsFactory;
  
  // Choose the desired widget factory based on the platform
  if (Theme.of(context).platform == TargetPlatform.iOS) {
    widgetsFactory = CupertinoWidgetsFactory();
  } else {
    widgetsFactory = MaterialWidgetsFactory();
  }
  
  // Use the selected factory to create widgets
  Widget button = widgetsFactory.createButton("Submit");
  Widget textField = widgetsFactory.createTextField("Enter text");
}

Bu örnekte, IWidgetsFactory arayüzü createButton ve createTextField adında iki metod tanımlar. MaterialWidgetsFactory ve CupertinoWidgetsFactory sınıfları bu arayüzü uygular ve her biri farklı türde Widget‘lar oluşturmak için bu metodların uygulamalarını sağlar. main metodunda, platforma göre istenen Widget fabrikası seçilir ve o fabrika aracılığıyla Widget‘lar oluşturulur.

IActivityIndicator

“IActivityIndicator” Flutter framework’ünün bir parçası olmayan teorik bir arayüzdür. Başka bir uygulamada özel bir aktivite göstergesi için bir arayüzü temsil edebilir. Flutter’da, CircularProgressIndicator widget’ını kullanarak dairesel bir aktivite göstergesi görüntüleyebilirsiniz ya da AnimatedOpacity, AnimatedBuilder ve Transform gibi diğer widget’ları kullanarak kendi özel aktivite göstergenizi oluşturabilirsiniz.

Aktivite göstergesi bileşeni (widget) için render() metodunu tanımlayan bir arayüz.

Aşağıdaki örnek, IActivityIndicator adında bir arayüz tanımlar ve bu arayüzü uygulayan bir sınıf (örneğin, CircularActivityIndicator) oluşturur:

abstract class IActivityIndicator {
  Widget render();
}

class CircularActivityIndicator implements IActivityIndicator {
  @override
  Widget render() {
    return CircularProgressIndicator();
  }
}

Bu sınıf, Flutter’daki CircularProgressIndicator widget’ını kullanarak dairesel bir aktivite göstergesi görüntüler. Eğer farklı bir aktivite göstergesi türü kullanmak isterseniz, IActivityIndicator arayüzünü uygulayan başka bir sınıf oluşturabilirsiniz.

ISlider

“ISlider” Flutter framework’ünün bir parçası olmayan teorik bir arayüzdür. Başka bir uygulamada özel bir slaytıcı için bir arayüzü temsil edebilir. Flutter’da, kullanıcının belirli bir aralıkta bir değer seçmesine olanak tanıyan bir slaytıcı görüntülemek için Slider widget’ını kullanabilirsiniz. Slider widget, değer değiştirmek için bir slaytıcı parmağı içerir ve bir yol boyunca sürülebilir. Slaytıcının görünümünü, parmak şeklini, yol rengini ve diğer özellikleri değiştirerek özelleştirebilirsiniz.

Bir slaytıcı bileşeni (widget) için render() metodunu tanımlayan bir arayüz.

Aşağıdaki örnek, ISlider adında bir arayüz tanımlar ve bu arayüzü uygulayan bir sınıf (örneğin, CustomSlider) oluşturur:

abstract class ISlider {
  Widget render();
}

class CustomSlider implements ISlider {
  double _value;

  CustomSlider({double value = 0.0}) : _value = value;

  @override
  Widget render() {
    return Slider(
      value: _value,
      onChanged: (double newValue) {
        _value = newValue;
      },
    );
  }
}

Bu sınıf, Flutter’daki Slider widget’ını kullanarak bir slaytıcı görüntüler ve değerini özelleştirmek için value ve onChanged özelliklerini ayarlar. Eğer farklı bir slaytıcı türü kullanmak isterseniz, ISlider arayüzünü uygulayan başka bir sınıf oluşturabilirsiniz.

ISwitch

Anahtar (switch) bileşeni (widget) için render() metodunu tanımlayan bir arayüz.

Bir örnek kod:

abstract class ISwitch {
  Widget render();
}

class CustomSwitch implements ISwitch {
  bool _value;

  CustomSwitch({bool value = false}) : _value = value;

  @override
  Widget render() {
    return Switch(
      value: _value,
      onChanged: (bool newValue) {
        _value = newValue;
      },
    );
  }
}

Bu sınıf, Flutter’daki Switch widget’ını kullanarak bir anahtar görüntüler ve değerini özelleştirmek için value ve onChanged özelliklerini ayarlar. Eğer farklı bir anahtar türü kullanmak isterseniz, ISwitch arayüzünü uygulayan başka bir sınıf oluşturabilirsiniz.

Örnek kod

import 'package:flutter/material.dart';

abstract class IWidgetsFactory {
  Widget createButton();
  Widget createTextField();
}

class MaterialWidgetsFactory implements IWidgetsFactory {
  @override
  Widget createButton() {
    return RaisedButton(
      child: Text('Material Button'),
      onPressed: () {},
    );
  }

  @override
  Widget createTextField() {
    return TextField(
      decoration: InputDecoration(
        hintText: 'Material Text Field',
      ),
    );
  }
}

class CupertinoWidgetsFactory implements IWidgetsFactory {
  @override
  Widget createButton() {
    return CupertinoButton(
      child: Text('Cupertino Button'),
      onPressed: () {},
    );
  }

  @override
  Widget createTextField() {
    return CupertinoTextField(
      placeholder: 'Cupertino Text Field',
    );
  }
}

class AbstractFactoryExample extends StatefulWidget {
  @override
  _AbstractFactoryExampleState createState() => _AbstractFactoryExampleState();
}

class _AbstractFactoryExampleState extends State<AbstractFactoryExample> {
  IWidgetsFactory _selectedFactory;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Abstract Factory Example'),
      ),
      body: Column(
        children: [
          DropdownButton<IWidgetsFactory>(
            items: [
              DropdownMenuItem(
                child: Text('Material'),
                value: MaterialWidgetsFactory(),
              ),
              DropdownMenuItem(
                child: Text('Cupertino'),
                value: CupertinoWidgetsFactory(),
              ),
            ],
            onChanged: (value) {
              setState(() {
                _selectedFactory = value;
              });
            },
            value: _selectedFactory,
          ),
          Expanded(
            child: _buildWidgets(),
          ),
        ],
      ),
    );
  }

  Widget _buildWidgets() {
    if (_selectedFactory == null) {
      return Container();
    }

    return Column(
      children: [
        _selectedFactory.createButton(),
        SizedBox(height: 20),
        _selectedFactory.createTextField(),
      ],
    );
  }
}


Bir yanıt yazın