Fabrika yöntemi deseni - Factory method pattern
In sınıf tabanlı programlama , fabrika yöntemi desen bir olan yaradılış desen kullanımları fabrika yöntemleri sorunuyla başa çıkmak için o nesneleri oluştururken kesin belirtmek zorunda kalmadan sınıf oluşturulacak nesnenin. Bu, bir yapıcı çağırmak yerine , bir arabirimde belirtilen ve alt sınıflar tarafından uygulanan veya bir temel sınıfta uygulanan ve isteğe bağlı olarak türetilmiş sınıflar tarafından geçersiz kılınan bir fabrika yöntemi çağrılarak nesneler yaratılarak yapılır .
genel bakış
Fabrika Yöntemi tasarım deseni, esnek ve yeniden kullanılabilir nesne yönelimli yazılım, yani uygulanması daha kolay nesneler tasarlamak için yinelenen tasarım problemlerinin nasıl çözüleceğini açıklayan yirmi üç iyi bilinen "Dörtlü Çete" tasarım modellerinden biridir . değiştirin, test edin ve yeniden kullanın.
Fabrika Yöntemi tasarım deseni aşağıdaki gibi sorunları çözer:
- Alt sınıfların hangi sınıfın başlatılacağını yeniden tanımlayabilmesi için bir nesne nasıl oluşturulabilir?
- Bir sınıf, somutlaştırmayı alt sınıflara nasıl erteleyebilir?
Fabrika Yöntemi tasarım deseni, bu tür sorunların nasıl çözüleceğini açıklar:
- Bir nesne oluşturmak için ayrı bir işlem ( fabrika yöntemi ) tanımlayın .
- Bir fabrika yöntemini çağırarak bir nesne oluşturun .
Bu, bir nesnenin oluşturulma şeklini değiştirmek için (hangi sınıfın somutlaştırılacağını yeniden tanımlamak için) alt sınıfların yazılmasını sağlar.
Ayrıca aşağıdaki UML sınıf şemasına bakın.
Tanım
"Bir nesne oluşturmak için bir arabirim tanımlayın, ancak hangi sınıfın somutlaştırılacağına alt sınıfların karar vermesine izin verin. Factory yöntemi, bir sınıfın kullandığı örneklemeyi alt sınıflara ertelemesine izin verir." ( Dörtlü Çete )
Bir nesne oluşturmak, genellikle, bir oluşturma nesnesine dahil edilmeye uygun olmayan karmaşık işlemler gerektirir. Nesnenin oluşturulması, kodun önemli bir yinelenmesine yol açabilir, oluşturan nesne tarafından erişilemeyen bilgiler gerektirebilir, yeterli düzeyde bir soyutlama sağlamayabilir veya başka türlü oluşturan nesnenin endişelerinin bir parçası olmayabilir . Fabrika yöntemi tasarım deseni , nesnelerin oluşturulması için ayrı bir yöntem tanımlayarak bu sorunları ele alır ; bu alt sınıflar daha sonra oluşturulacak türetilmiş ürün türünü belirtmek için geçersiz kılabilir .
Fabrika yöntemi deseni, nesne oluşturma, nesneler oluşturmak için fabrika yöntemini uygulayan alt sınıflara devredildiğinden mirasa dayanır.
Yapı
UML sınıf diyagramı
Yukarıdaki UML sınıf diyagramında , Creatorbir Productnesne gerektiren Product1sınıf , sınıfı doğrudan başlatmaz . Bunun yerine, hangi somut sınıfın somutlaştırıldığını bağımsız kılan bir ürün nesnesi oluşturmak Creatoriçin ayrı anlamına gelir . öğesinin alt sınıfları, hangi sınıfın somutlaştırılacağını yeniden tanımlayabilir. Bu örnekte, alt sınıf , sınıfı somutlaştırarak özeti uygular .
factoryMethod()CreatorCreatorCreator1factoryMethod()Product1
Örnek
Bir labirent oyunu iki modda oynanabilir, biri yalnızca bitişik odalarla bağlantılı normal odalarla, diğeri ise oyuncuların rastgele taşınmasına izin veren sihirli odalarla.
Yapı
Roomnihai ürün ( MagicRoomveya OrdinaryRoom) için temel sınıftır . MazeGameböyle bir temel ürünü üretmek için soyut fabrika yöntemini ilan eder. MagicRoomve OrdinaryRoomnihai ürünü uygulayan temel ürünün alt sınıflarıdır. MagicMazeGameve nihai ürünleri üreten fabrika yöntemini uygulamanın OrdinaryMazeGamealt sınıflarıdır MazeGame. Böylece fabrika yöntemleri, arayanları ( MazeGame) somut sınıfların uygulanmasından ayırır. Bu, "yeni" Operatörü gereksiz kılar, Açık/kapalı ilkesine bağlı kalmaya izin verir ve değişiklik durumunda nihai ürünü daha esnek hale getirir.
Örnek uygulamalar
C#
// Empty vocabulary of actual object
public interface IPerson
{
string GetName();
}
public class Villager : IPerson
{
public string GetName()
{
return "Village Person";
}
}
public class CityPerson : IPerson
{
public string GetName()
{
return "City Person";
}
}
public enum PersonType
{
Rural,
Urban
}
/// <summary>
/// Implementation of Factory - Used to create objects.
/// </summary>
public class Factory
{
public IPerson GetPerson(PersonType type)
{
switch (type)
{
case PersonType.Rural:
return new Villager();
case PersonType.Urban:
return new CityPerson();
default:
throw new NotSupportedException();
}
}
}
Yukarıdaki kodda aradığınız bir arayüz oluşturulmasını görebilirsiniz IPersonve denilen iki uygulamaları Villagerve CityPerson. FactoryNesneye iletilen türe bağlı olarak, orijinal somut nesneyi interface olarak döndürüyoruz IPerson.
Bir fabrika yöntemi, yalnızca Factorysınıfa bir ektir . Arayüzler aracılığıyla sınıfın nesnesini yaratır, ancak diğer yandan, alt sınıfın hangi sınıfın somutlaştırılacağına karar vermesine de izin verir.
public interface IProduct
{
string GetName();
bool SetPrice(double price);
}
public class Phone : IProduct
{
private double _price;
public string GetName()
{
return "Apple TouchPad";
}
public bool SetPrice(double price)
{
_price = price;
return true;
}
}
/* Almost same as Factory, just an additional exposure to do something with the created method */
public abstract class ProductAbstractFactory
{
protected abstract IProduct MakeProduct();
public IProduct GetObject() // Implementation of Factory Method.
{
return this.MakeProduct();
}
}
public class PhoneConcreteFactory : ProductAbstractFactory
{
protected override IProduct MakeProduct()
{
IProduct product = new Phone();
// Do something with the object after you get the object.
product.SetPrice(20.30);
return product;
}
}
MakeProductBeton fabrikasında kullandığımızı görebilirsiniz . Sonuç olarak, MakeProduct()almak için ondan kolayca arayabilirsiniz IProduct. Nesneyi somut Fabrika Yönteminde aldıktan sonra özel mantığınızı da yazabilirsiniz. GetObject, Factory arayüzünde soyut hale getirilir.
Java
Bu Java örneği, Design Patterns kitabındakine benzer .
MazeGame Odalar'ı kullanır ancak Odalar oluşturma sorumluluğunu somut sınıfları oluşturan alt sınıflarına verir. Normal oyun modu bu şablon yöntemini kullanabilir:
public abstract class Room {
abstract void connect(Room room);
}
public class MagicRoom extends Room {
public void connect(Room room) {}
}
public class OrdinaryRoom extends Room {
public void connect(Room room) {}
}
public abstract class MazeGame {
private final List<Room> rooms = new ArrayList<>();
public MazeGame() {
Room room1 = makeRoom();
Room room2 = makeRoom();
room1.connect(room2);
rooms.add(room1);
rooms.add(room2);
}
abstract protected Room makeRoom();
}
Yukarıdaki snippet'te MazeGameyapıcı, bazı ortak mantıklar oluşturan bir şablon yöntemidir . makeRoomDiğer odaların bir alt sınıfta kullanılabilmesi için odaların oluşturulmasını kapsayan fabrika yöntemini ifade eder . Sihirli odaları olan diğer oyun modunu uygulamak için makeRoomyöntemi geçersiz kılmak yeterlidir :
public class MagicMazeGame extends MazeGame {
@Override
protected Room makeRoom() {
return new MagicRoom();
}
}
public class OrdinaryMazeGame extends MazeGame {
@Override
protected Room makeRoom() {
return new OrdinaryRoom();
}
}
MazeGame ordinaryGame = new OrdinaryMazeGame();
MazeGame magicGame = new MagicMazeGame();
PHP
PHP'deki başka bir örnek , bu sefer alt sınıflama yerine arayüz uygulamalarını kullanarak (ancak aynısı alt sınıflama yoluyla da elde edilebilir). Fabrika yönteminin de genel olarak tanımlanabileceğini ve doğrudan istemci koduyla çağrılabileceğini (yukarıdaki Java örneğinin aksine) not etmek önemlidir.
/* Factory and car interfaces */
interface CarFactory
{
public function makeCar(): Car;
}
interface Car
{
public function getType(): string;
}
/* Concrete implementations of the factory and car */
class SedanFactory implements CarFactory
{
public function makeCar(): Car
{
return new Sedan();
}
}
class Sedan implements Car
{
public function getType(): string
{
return 'Sedan';
}
}
/* Client */
$factory = new SedanFactory();
$car = $factory->makeCar();
print $car->getType();
piton
Java örneğiyle aynı.
from abc import ABC, abstractmethod
class MazeGame(ABC):
def __init__(self) -> None:
self.rooms = []
self._prepare_rooms()
def _prepare_rooms(self) -> None:
room1 = self.make_room()
room2 = self.make_room()
room1.connect(room2)
self.rooms.append(room1)
self.rooms.append(room2)
def play(self) -> None:
print('Playing using "{}"'.format(self.rooms[0]))
@abstractmethod
def make_room(self):
raise NotImplementedError("You should implement this!")
class MagicMazeGame(MazeGame):
def make_room(self):
return MagicRoom()
class OrdinaryMazeGame(MazeGame):
def make_room(self):
return OrdinaryRoom()
class Room(ABC):
def __init__(self) -> None:
self.connected_rooms = []
def connect(self, room) -> None:
self.connected_rooms.append(room)
class MagicRoom(Room):
def __str__(self):
return "Magic room"
class OrdinaryRoom(Room):
def __str__(self):
return "Ordinary room"
ordinaryGame = OrdinaryMazeGame()
ordinaryGame.play()
magicGame = MagicMazeGame()
magicGame.play()
kullanır
- Gelen ADO.NET , IDbCommand.CreateParameter paralel sınıf hiyerarşileri bağlamak için fabrika yöntemi kullanımının bir örnektir.
- In Qt , QMainWindow :: createPopupMenu bir fabrika yöntemi geçersiz kılınan olabilir bir çerçevede ilan olduğunu uygulama kodu .
- In Java , çeşitli fabrikalar kullanılan javax.xml.parsers paketinde. örneğin javax.xml.parsers.DocumentBuilderFactory veya javax.xml.parsers.SAXParserFactory.
- Gelen HTML5 DOM API , belge arayüzü HTMLElement arayüzün belli elemanlarını oluşturmak için bir createElement fabrika yöntem içerir.
Ayrıca bakınız
- Tasarım Desenleri , son derece etkili kitap
- Tasarım deseni , genel olarak tasarım desenlerine genel bakış
- Soyut fabrika kalıbı , genellikle fabrika yöntemleri kullanılarak uygulanan bir kalıp
- Oluşturucu kalıbı , başka bir yaratılış kalıbı
- Fabrika yöntemlerini çağırabilen şablon yöntemi deseni
- Joshua Bloch'un Tasarım Modellerinde doğrudan bir karşılığı olmadığını söylediği statik fabrika yöntemi fikri .
Referanslar
- Martin Fowler ; Kent Beck ; John Brant ; William Opdyke ; Don Roberts (Haziran 1999). Yeniden Düzenleme: Mevcut Kodun Tasarımını İyileştirme . Addison-Wesley. ISBN'si 0-201-48567-2.
- Gama, Erich ; Helm, Richard ; Johnson, Ralph; Vlissides, John (1994). Tasarım Modelleri: Yeniden Kullanılabilir Nesne Yönelimli Yazılımın Unsurları . Addison-Wesley. ISBN'si 0-201-63361-2.
- Cox, Brad J. (1986). Nesne yönelimli programlama: evrimsel bir yaklaşım . Addison-Wesley. ISBN'si 978-0-201-10393-9.
- Cohen, Tal; Gil, Yusuf (2007). "Fabrikalarla Daha İyi İnşaat" (PDF) . Nesne Teknolojisi Dergisi . Bertrand Meyer . 6 (6): 103. doi : 10.5381/jot.2007.6.6.a3 . 2007-03-12 alındı .
Dış bağlantılar
- Java'da Fabrika Tasarım Modeli Uygulaması
- UML ve LePUS3'te fabrika yöntemi (bir Tasarım Tanımlama Dili)
- Joshua Bloch'un statik fabrika yöntemlerini düşünün
