设计类链

时间:2011-05-27 10:38:29

标签: c# design-patterns ldap

我有一个用于ldap操作的第三方C#库。它对连接对象执行所有操作,如下所示:

LdapConnection connection = new LdapConnetion(Settings settings);
connection.Search(searchOU, filter,...);

我认为这是不可读的。我想写一个包装器,以便我能够编写如下代码:

因为我想拥有不同的Ldap类,比如

public class AD: LdapServer { }
public class OpenLdap: LdapServer { }

然后

AD myldap = new AD(Settings settings);
myldap.Users.Search(searchOU, filter,...)
myldap.Users.Add(searchOU, filter,...)
myldap.Users.Delete(searchOU, filter,...)

我正在考虑代理设计模式,但事情并没有让我感到热心。我应该有什么课程等。

任何帮助?

2 个答案:

答案 0 :(得分:0)

好的,如果您只是想将方法拆分为它们所依据的对象(例如在您的示例中,在方法调用之前添加.Users。)您可以执行与此类似的操作。您需要获取正确的库方法参数和返回类型,我刚刚在这里使用了对象。

这是你要找的东西吗?

public class AD : LdapConnection
{
    private UsersWrapper users;

    public AD(Settings settings) : base(settings)
    {
        this.users = new UsersWrapper(this);
    }

    public UsersWrapper Users
    {
        get
        {
            return this.users;
        }
    }

    public class UsersWrapper
    {
        private AD parent;

        public UsersWrapper(AD parent)
        {
            this.parent = parent;
        }

        public object Search()
        {
            return this.parent.Search();
        }

        public void Add(object something)
        {
            this.parent.Add(something);
        }

        public void Delete(object something)
        {
            this.parent.Delete(something);
        }
    }
}

然后可以按如下方式使用:

Settings settings = new Settings();
AD myAD = new AD(settings);

object results = myAD.Users.Search();

请记住,这不是严格意义上的“包装器”,因为它实际上是从底层类继承的。

答案 1 :(得分:0)

上面发布的解决方案继承自LdapConnection。如果你想维护继承链,这很好,但我认为在你的情况下这是必要的。您只想自定义和简化界面。

代理设计模式继承自底层对象,因此代理对象可以在需要底层对象的任何地方使用,如果你想在类中“注入”额外的功能而没有实现该类的客户端,这是很好的。我不认为这是你的意图吗?

上面发布的解决方案的一个大问题是(因为它直接从LdapConnection继承),您可以通过两种方式调用搜索:

Settings settings = new Settings();
AD myAD = new AD(settings);

object results = myAD.Users.Search();
// OR
object results2 = myAD.Search();

我确信你可以从代码中看到,这两个都调用完全相同的底层方法。但在我看来,这对开发人员来说比使用vanilla LdapConnection对象更加困惑。我会一直在想“这些看似相同的方法之间的区别是什么?”更糟糕的是,如果在UsersWrapper Search方法中添加一些自定义代码,则无法始终保证它将被调用。开发人员可以直接调用搜索,而无需通过UsersWrapper。

Fowler在他的书PoEAA中定义了一种名为Gateway的模式。这是一种简化和自定义外部系统或库接口的方法。

public class AD
{
    private LdapConnection ldapConn;
    private UsersWrapper users;

    public AD()
    {
        this.ldapConn = new LdapConnection(new Settings(/* configure settings here*/));
        this.users = new UsersWrapper(this.ldapConn);
    }

    public UsersWrapper Users
    {
        get
        {
            return this.users;
        }
    }

    public class UsersWrapper
    {
        private LdapConnection ldapConn;

        public UsersWrapper(LdapConnection ldapConn)
        {
            this.ldapConn = ldapConn;
        }

        public object Search()
        {
            return this.ldapConn.Search();
        }

        public void Add(object something)
        {
            this.ldapConn.Add(something);
        }

        public void Delete(object something)
        {
            this.ldapConn.Delete(something);
        }
    }
}

然后可以这样使用:

AD myAD = new AD();
object results = myAD.Users.Search();

在这里,您可以看到LdapConnection对象被完全封装在类中,并且只有一种方法可以调用每个方法。更好的是,LdapConnection的设置也是完全封装的。使用此类的代码不必担心如何设置它。这些设置仅在一个地方定义(在此课程中,而不是在整个应用程序中传播)。

唯一的缺点是你将继承链松散回LdapConnection,但我认为这不是必要的。