Abstract Factory tasarım deseni birbirleri ile ilişkili ürün ailesini oluşturmak için bir arayüz sağlar.
Factory tasarım deseninde bir ürünün oluşturulması soyutlanmış iken Abstract Factory deseninde birbirleri ile ilişkili ürün ailelerininin oluşturulması soyutlanmıştır. Factory üreten Factory deseni olarak da düşünülebilir. 🧐
Anlayacağımız; birden fazla ürün ailesi ile çalışmak zorunda kaldığımız durumlarda, istemciyi bu yapılardan soyutlamak için Abstract Factory doğru bir yaklaşım olacaktır.
ProductA, ProductB: Temel sınıflarımız, soyuttur ve oluşturulmasını istediğimiz sınıflar bunlardan türer.
ConcreteProduct: Üretmek istediğimiz sınıflardır.
AbstractFactory: Herbir sınıfın oluşturulması için metotların tanımlandığı arayüzdür.
ConcreteFactory: AbstractFactory arayüzünü uygulayarak gerekli sınıfların oluşturulmasını sağlar.
Şöyle bir senaryo düşünülebilir; sistemimiz isteğe bağlı Oracle ya da MySQL için sorgu çalıştırabilir olsun. Bu işlemler için temel olarak da bağlantının açılması, kapatılması ve sorgunun çalıştırılması gerekli olduğu varsayalım. Bu işlemler direkt olarak herbiri Factory desen olarak ayarlanabilir ama birbirleri ile ilişkili aileden geldikleri için bu desene daha sağlıklı olacaktır.
C# Kod Örneği:
// Soyut sınıfımızdır.// UML'deki Product sınıfına denk gelmektedir.publicabstractclassCommand{publicabstractvoidExecuteCommand(string query);}
// Command sınıfından türer.// UML'deki ConcreteProduct sınıfına denk gelmektedir.classMySQLCommand:Command{publicoverridevoidExecuteCommand(string query) { // Gelen sorgunun çalıştırılması için // Gerekli operasyonel işlemler... }}
// Command sınıfından türer.// UML'deki ConcreteProduct sınıfına denk gelmektedir.classOracleCommand:Command{publicoverridevoidExecuteCommand(string query) { // Gelen sorgunun çalıştırılması için // Gerekli operasyonel işlemler... }}
// Soyut sınıfımızdır.// UML'deki Product sınıfına denk gelmektedir.abstractclassConnection{publicabstractboolOpenConnection();publicabstractboolCloseConnection();}
// Connection sınıfından türer.// UML'deki ConcreteProduct sınıfına denk gelmektedir.classMySQLConnection:Connection{publicoverrideboolOpenConnection() { // MySQL veri tabanı bağlantısının açılması için // Gerekli operasyonel işlemler...returntrue; }publicoverrideboolCloseConnection() { // MySQL veri tabanı bağlantısının kapatılması için // Gerekli operasyonel işlemler...returntrue; }}
// Connection sınıfından türer.// UML'deki ConcreteProduct sınıfına denk gelmektedir.classOracleConnection:Connection{publicoverrideboolOpenConnection() { // Oracle veri tabanı bağlantısının açılması için // Gerekli operasyonel işlemler...returntrue; }publicoverrideboolCloseConnection() { // Oracle veri tabanı bağlantısının kapatılması için // Gerekli operasyonel işlemler...returntrue; }}
// Oluşturulacak ürünlere ait metotları içerir.// UML'deki AbstractFactory sınıfına denk gelmektedir.interfaceIDatabaseFactory{ConnectionCreateConnection();CommandCreateCommand();}
// Oracle için ilişkili nesneler üretildi.// UML'deki ConcreteFactory sınıfına denk gelmektedir.classOracleDatabaseFactory:IDatabaseFactory{publicCommandCreateCommand() {returnnewOracleCommand(); }publicConnectionCreateConnection() {returnnewOracleConnection(); }}
// MySQL için ilişkili nesneler üretildi.// UML'deki ConcreteFactory sınıfına denk gelmektedir.classMySQLDatabaseFactory:IDatabaseFactory{publicCommandCreateCommand() {returnnewMySQLCommand(); }publicConnectionCreateConnection() {returnnewMySQLConnection(); }}
// IDatabaseFactory arayüzünü uygulayan sınıfları// Kullanarak temel operasyonel işlemleri yapan bir sınıf.classCustomOperation{IDatabaseFactory _databaseFactory;Connection _connection;Command _command;publicCustomOperation(IDatabaseFactory databaseFactory) { _databaseFactory = databaseFactory; _command =databaseFactory.CreateCommand(); _connection =databaseFactory.CreateConnection(); }publicvoidRemoveById(int id) {_connection.OpenConnection();_command.ExecuteCommand("DELETE ...");_connection.CloseConnection(); }}