La compréhension de la Façon de Créer une Interface Fluide
Salut, je suis en train d'essayer de comprendre comment je pouvais construire un lisible et aussi l'erreur empêchant le Fluide-API sans trop de restriction pour l'Utilisateur
pour le maintenir simple disons que nous voulons changer la classe suivante, être à l'aise
public class Car
{
public int Gallons { get; private set; }
public int Tons { get; private set; }
public int Bhp { get; private set; }
public string Make { get; private set; }
public string Model { get; private set; }
public Car(string make, string model)
{
Make = make;
Model = model;
}
public void WithHorsePower(int bhp)
{
Bhp = bhp;
return this;
}
public void WithFuel(int gallons)
{
Gallons = gallons;
}
public void WithWeight(int tons)
{
Tons = tons;
}
public int Mpg()
{
return Gallons/Tons;
}
}
le problème dans ce cas, l'utilisateur doit seulement être en mesure d'accéder à Mpg()
si Weight()
et Fuel()
ai appelé d'abord la position de HorsePower()
n'est pas pertinent.
Échantillons:
int mpg =Car.Create().HorsePower().Fuel().Weight().Mpg();
int mpg =Car.Create().Fuel().HorsePower().Weight().Mpg();
int mpg =Car.Create().HorsePower().Fuel().HorsePower().Weight().Mpg();//<- no typo
int mpg =Car.Create().Fuel().Weight().HorsePower().Mpg();
int mpg =Car.Create().Weight().HorsePower().Fuel().Mpg();
int mpg =Car.Create().Weight().Fuel().Mpg();
Est-il un moyen facile de le faire sans un gros tas d'interfaces?
Je ne pas comment mettre en place cette des interfaces imbriquées dans le droit chemin
Ici sont les interfaces que j'ai actuellement créé
interface Start
{
IFuelWeight1 HorsePower();
IHorsePowerWeight1 Fuel();
IHorsePowerFuel1 Weight();
}
interface IFuelWeight1 //Start.HorsePower()
{
IHorsePowerWeight1 Fuel();
IHorsePowerFuel1 Weight();
}
interface IHorsePowerWeight1 //Start.Fuel()
{
IHorsePowerWeight1 HorsePower();
IHorsePowerFuelMpg Weight();
}
interface IHorsePowerFuel1 //Start.Weight()
{
IHorsePowerFuel1 HorsePower();
IHorsePowerWeightMpg Fuel();
}
#region End
interface IHorsePowerFuelMpg
{
IFuelWeightMpg HorsePower();
IHorsePowerWeightMpg Fuel();
int Mpg();
}
interface IHorsePowerWeightMpg
{
IFuelWeightMpg HorsePower();
IHorsePowerFuelMpg Weight();
int Mpg();
}
interface IFuelWeightMpg
{
IHorsePowerWeightMpg Fuel();
IHorsePowerFuelMpg Weight();
int Mpg();
}
#endregion
MODIFIER pour Adam Houldsworth 🙂
- Est l'Interface ci-dessus un bon ou est-il un moyen plus facile de le faire
mais tenir la restriction pour Mpg()? - Comment Implémenter l'interface ci-dessus pour ce faire?:
var k = myMiracle as Start; k.Fuel().Weight(); k.Weight().Fuel(); k.HorsePower().Fuel().Weight(); k.HorsePower().Weight().Fuel(); k.Fuel().HorsePower().Weight(); k.Weight().HorsePower().Fuel();
WithXXX
méthodes de retourner Car
et simplement return this;
à la fin de chaque méthode? Ensuite, vous pouvez var car = new Car().WithFuel(100).WithMpg(35).WithHorsePower(200);
. Sinon, juste de le rendre optionnel arguments du constructeur 🙂Désolé, je pensais que le but de cette question était de le faire plus facilement que les charges d'interfaces, de retour de l'article en lui-même est simple. Je voudrais déplacer loin de buzzword implémentations telles que "fluent" et vers le standard et ennuyeux paramètres du constructeur et des méthodes standard.
Ce n'est pas que je ne voudrais pas l'utiliser, mais je pense qu'il a réduit les scénarios où il fonctionne bien. Je n'ai jamais eu besoin de la mettre en œuvre spécifiquement moi-même pour améliorer l'utilisation d'une classe ou d'un type.
Personnellement, je pense que l'on peut polluer une interface publique s'il n'est pas fait avec soin.
Je voudrais également ajouter que, si elle n'est pas valide pour un
Car
être initialisé sans Weight
ou Mpg
par exemple, alors vous ces paramètres dans le cadre de l'constructeur... sinon, vous allez permettre aux utilisateurs de créer un Car
qui est dans un état non valide et il n'y a pas de montant de "gentillesse", qui parlait couramment l'interface peut offrir de corriger ça (ça ne vaut pas le trade-off). Couramment interfaces peut être utile, mais dans ce cas particulier vous le faites mal. Désolé!OriginalL'auteur WiiMaxx | 2013-09-17
Vous devez vous connecter pour publier un commentaire.
Une alternative pourrait être d'invoquer toutes les opérations sur Mpg() qui permettra à la autres opérations conditionnelles.
C'est déjà répondu dans un exemple de code. Veuillez vous référer à Conditionnel Du Générateur De Chaînage De Méthode Interface Fluide
Du post l'indique, au lieu d'Interfaces, la même chose pourrait être réalisé en utilisant des constructeurs, avec un appel de méthode qui rend toutes les autres opérations conditionnelles.
OriginalL'auteur Consult Yarla
API Fluent est une belle chose, mais j'aimerais y aller d'une manière différente dans votre cas. La construction d'une voiture m'attire de plus en plus vers le Le générateur de modèle. De cette façon, vous permettrait de masquer une voiture étant composé dans une usine (l'usine méthode pattern) qui accepte des commandes que vous avez maintenant, mais ne pas accepter les questions.
Aucun fabricant vous permet de connaître tous les détails de leur nouvelle voiture, sauf si c'est terminé et prêt à être annoncé. Donc, vous devez envoyer une commande comme
GetMyCar()
pour libérer une voiture en premier, et il serait parfaitement logique que si vous appelezMpg
sur inachevé voiture, vous obtiendrez une exception. Et il serait toujours bon, si vous l'utiliser couramment le modèle.Ok, c'est mon opinion. Cependant, il ya deux plus de suggestions pour votre situation actuelle, vous pouvez choisir si vous n'aimez pas le constructeur.
1) Si l'utilisateur appelle
Mpg
avantWeight
etFuel
sont ensemble, la levée d'une exception avec un message expliquant la situation. Également ajouter une documentation appropriéeMpg
méthode.2) Faire un constructeur de prendre tous les paramètres requis pour les autres propriétés. C'est, à mon avis, une solution meilleure que la première, car elle dit depuis le début, ce que vous pouvez attendre.
OriginalL'auteur Ondrej Janacek