Disons qu'il existe une classe Foo, qui définit son comportement à l'aide des fonctions F1, F2, F3. Il y a peu de clients qui étendent le comportement de Foo et le personnalise selon leurs besoins.Motif de conception à appliquer Filtre de personnalisation
Pour ce scénario avant son droit de mettre en œuvre comme
class Foo
{
public:
virtual void F1() { // default behavior }
virtual void F2() { // default behavior }
virtual void F3() { // default behavior }
}
class CustomFoo1 : public Foo
{
public:
void F1() override { // customized behavior }
void F11() { // CustomFoo1's own methods }
}
class CustomFoo2 : public Foo
{
public:
void F1() override { // customized behavior }
void F21() { // CustomFoo2's own methods }
void F22() { // CustomFoo2's own methods }
}
droit? Mais cela n'est possible que si ma bibliothèque expose Class Foo pour d'autres clients pour créer CustomFoo1 et CustomFoo2. Je ne veux pas exposer ma mise en œuvre concrète, mais plutôt utiliser une interface que d'autres peuvent utiliser. Donc, je peux changer mon implémentation comme:
interface IFoo // Public interface
{
public:
virtual void F1() = 0;
virtual void F2() = 0;
virtual void F3() = 0;
}
Class Foo : public IFoo // Internal to library
{
public:
virtual void F1() override { // default behavior }
virtual void F2() override { // default behavior }
virtual void F3() override { // default behavior }
}
static IFoo* CreateFoo() { return new Foo(); }
class CustomFoo1 : public IFoo
{
public:
void F1() override { // Custom Behavior }
void F2() override { pFoo->F2(); // Need default so delegate call to default implementation }
void F3() override { pFoo->F3(); // Need default so delegate call to default implementation }
void F11() { // personal own implementation }
private:
IFoo* pFoo;
}
Même chose sera faite pour CustomFoo2. Mais ici, si vous voyez, je peux cacher mon implémentation concrète derrière l'interface, mais cela a amené mes clients à implémenter l'interface entière et à déléguer l'appel à l'implémentation par défaut de la bibliothèque si les classes personnalisées ne veulent pas remplacer comportement. Donc, je ne pense pas que ce soit une bonne solution non plus.
Cela me fait penser à la prochaine solution possible. Si vous regardez de plus près, les clients de la bibliothèque cherchent vraiment à personnaliser uniquement F1(). donc je déclare une autre interface dire IFooCustomizePolicy
interface IFooCustomizePolicy
{
public:
virtual void F1Customized() = 0;
}
Je modifierai IFoo comme:
interface IFoo // Public interface
{
public:
virtual void F1() = 0;
virtual void F2() = 0;
virtual void F3() = 0;
virtual void RegisterCustomizationPolicy(IFooCustomizePolicy* pPolicy) = 0;
}
Mise à jour la mise en œuvre du béton comme:
Class Foo : public IFoo // Internal to library
{
public:
void F1() override
{
if(pPolicy != nullptr)
pPolicy->F1Customized();
else
// default behavior
}
void F2() override { // default behavior }
void F3() override { // default behavior }
void RegisterCustomizationPolicy(IFooCustomizePolicy* pPolicy) override
{ this->pPolicy = pPolicy; }
private:
IFooCustomizePolicy* pPolicy;
}
et d'autres clients sera modifié comme suit:
class CustomFoo1 : public IFooCustomizePolicy
{
public:
void F1Customized() override { // customized behavior }
void F11() { //CustomFoo1's own methods }
}
Maintenant, si vous voyez, avec cette approche, je suis capable de cacher ma classe concrète, mais capable de fournir un comportement par défaut au client avec la façon de le personnaliser. Maintenant, disons que les exigences changent et qu'un nouveau client arrive et demande que la nouvelle méthode soit personnalisable. Dans ce cas, je devrais mettre à jour Policy Interface, ce qui est acceptable, c'est acceptable. Mais avec ce que je devrais faire est de mettre à jour la méthode correspondante de Foo pour respecter la politique et ajouter la logique ci-dessous aux méthodes chaque fois qu'ils sont ajoutés à la politique.
if(policy present) then call policy customized method
else continue with default behavior
Si vous voyez ici, ce que je veux vraiment est une sorte de filtre, Si mon objet a la politique puis filtrer devrait appeler la méthode de la politique et ne doit pas poursuivre la mise en œuvre par défaut. Mais je ne suis pas sûr quel modèle appliquer et comment?
Je pense qu'un modèle de conception de pont peut bien fonctionner ici afin que l'interface puisse être séparée de l'implémentation. – seccpur