Benim için, bu noktaya gelindiğinde, sadece kodunuzu yazmayı daha kolay / hızlı hale getirmek için bir şeyler olarak bakmayı bıraktığınızda netleşti - bu onların amacı değil. Birkaç kullanımları vardır:
(Bu, pizza benzetmesini kaybedecek, çünkü bunun kullanımını görselleştirmek çok kolay değil)
Ekranda basit bir oyun yaptığınızı ve etkileşimde bulunduğunuz yaratıkların olacağını söyleyin.
C: Ön uç ile arka uç uygulamanız arasında gevşek bir bağlantı sağlayarak kodunuzun gelecekte korunmasını kolaylaştırabilirler.
Başlamak için bunu yazabilirsiniz, çünkü sadece troller olacak:
// This is our back-end implementation of a troll
class Troll
{
void Walk(int distance)
{
//Implementation here
}
}
Başlangıç aşaması:
function SpawnCreature()
{
Troll aTroll = new Troll();
aTroll.Walk(1);
}
İki hafta boyunca, pazarlama, Twitter'da onlar hakkında okudukları için Orklara da ihtiyacınız olduğuna karar verir, böylece aşağıdaki gibi bir şey yapmanız gerekir:
class Orc
{
void Walk(int distance)
{
//Implementation (orcs are faster than trolls)
}
}
Başlangıç aşaması:
void SpawnCreature(creatureType)
{
switch(creatureType)
{
case Orc:
Orc anOrc = new Orc();
anORc.Walk();
case Troll:
Troll aTroll = new Troll();
aTroll.Walk();
}
}
Ve bunun nasıl dağınık hale geldiğini görebilirsiniz. Burada bir arabirim kullanabilirsiniz, böylece ön ucunuz bir kez yazılır ve (burada önemli olanı) test edilir ve daha sonra gerektiğinde daha fazla arka uç öğesi ekleyebilirsiniz:
interface ICreature
{
void Walk(int distance)
}
public class Troll : ICreature
public class Orc : ICreature
//etc
Ön uç o zaman:
void SpawnCreature(creatureType)
{
ICreature creature;
switch(creatureType)
{
case Orc:
creature = new Orc();
case Troll:
creature = new Troll();
}
creature.Walk();
}
Ön uç şimdi sadece ICreature arayüzünü önemsiyor - bir trolün veya bir orkın dahili uygulamasıyla ilgili değil, sadece ICreature'ı uyguladıkları gerçeğiyle ilgili.
Buna bu açıdan bakıldığında dikkat edilmesi gereken önemli bir nokta, soyut bir yaratık sınıfını da kolayca kullanabilmeniz ve bu açıdan da aynı etkiye sahip olmasıdır.
Ve yaratılışı bir fabrikaya çıkarabilirsiniz:
public class CreatureFactory {
public ICreature GetCreature(creatureType)
{
ICreature creature;
switch(creatureType)
{
case Orc:
creature = new Orc();
case Troll:
creature = new Troll();
}
return creature;
}
}
Ve sonra ön ucumuz şöyle olur:
CreatureFactory _factory;
void SpawnCreature(creatureType)
{
ICreature creature = _factory.GetCreature(creatureType);
creature.Walk();
}
Ön uç artık Troll ve Orc'un uygulandığı kütüphaneye bir referansa sahip olmak zorunda bile değil (fabrikanın ayrı bir kütüphanede olması koşuluyla) - onlar hakkında hiçbir şey bilmesine gerek yok.
B: Aksi takdirde homojen veri yapınızda yalnızca bazı canlıların sahip olacağı işlevselliğe sahip olduğunuzu varsayalım , ör.
interface ICanTurnToStone
{
void TurnToStone();
}
public class Troll: ICreature, ICanTurnToStone
Ön uç şu şekilde olabilir:
void SpawnCreatureInSunlight(creatureType)
{
ICreature creature;
switch(creatureType)
{
case Orc:
creature = new Orc();
case Troll:
creature = new Troll();
}
creature.Walk();
if (creature is ICanTurnToStone)
{
(ICanTurnToStone)creature.TurnToStone();
}
}
C: Bağımlılık enjeksiyonu için kullanım
Bağımlılık enjeksiyon çerçevelerinin çoğu, ön uç kodu ile arka uç uygulaması arasında çok gevşek bir bağlantı olduğunda çalışmak daha kolaydır. Yukarıdaki fabrika örneğimizi alırsak ve fabrikamızın bir arayüz uygulamasını sağlarsak:
public interface ICreatureFactory {
ICreature GetCreature(string creatureType);
}
Ön ucumuz, yapıcı (tipik olarak) aracılığıyla bu enjekte edilebilir (örn., Bir MVC API denetleyicisi):
public class CreatureController : Controller {
private readonly ICreatureFactory _factory;
public CreatureController(ICreatureFactory factory) {
_factory = factory;
}
public HttpResponseMessage TurnToStone(string creatureType) {
ICreature creature = _factory.GetCreature(creatureType);
creature.TurnToStone();
return Request.CreateResponse(HttpStatusCode.OK);
}
}
DI çerçevemizle (örneğin Ninject veya Autofac), bunları bir kurucuda bir ICreatureFactory gerektiğinde CreatureFactory'nin bir örneğinin oluşturulacağı şekilde ayarlayabiliriz - bu kodumuzu güzel ve basit hale getirir.
Ayrıca, denetleyicimiz için birim testi yazdığımızda, sahte bir ICreatureFactory sağlayabiliriz (örneğin, somut uygulama DB erişimi gerektiriyorsa, birim testlerimizin buna bağlı olmasını istemiyoruz) ve denetleyicimizdeki kodu kolayca test edebiliriz .
D: Örneğin, 'eski' nedenlerden dolayı iyi yapılandırılmamış iki A ve B projeniz var ve A'nın B'ye referansı var.
Daha sonra B'de zaten A'da bir yöntem çağırması gereken işlevsellik bulursunuz. Dairesel bir başvuru alırken somut uygulamaları kullanarak bunu yapamazsınız.
B'de, A'daki sınıfın uyguladığı bir arabirim olabilir. B'deki yönteminiz, somut nesne A'da bir tür olmasına rağmen, arabirimi sorunsuz bir şekilde uygulayan bir sınıfın örneğinden geçirilebilir.