0

所以,这是我的设计。AccessDecorator类有对另一个的引用,Access就像普通的装饰器模式一样。

设计

但问题是当我创建一个AccessDecorator包装 aConcreteAccess然后尝试查看 Access 是哪种类型时:

Access access = new InAllowedAccess();
Access wrapperAccess = new MismatchAccess(access); 
if (wrapperAccess instanceof InAllowedAccess)   //this condition could be used to be a predicate for a filtering over an access list for example
    //do something

当然这行不通,因为wrapperAccess不是类型InAllowedAccess ,但我真正想知道的是 some 的所有类型Access在这种情况下, thewrapperAccess不仅是类型MismatchAccess,而且是类型InAllowedAccess

我考虑过在类中实现 , 和 , 之类的方法,isInstanceofInAllowed()但似乎不是isInstanceofOutAllowed()一个好的解决方案,我不知道......isInstanceofInDenied()isinstanceofOutDenied()isinstanceofMismatch()Access

否则我应该MismatchAccesses为每 4 种类型创建一个大的分层树InAllowedMismatchAccessOutAllowedMismatchAccess和?然后,当我开发另一个装饰器时?...InDeniedMismatchAccessOutDeniedMismatchAccess

还是有其他更好的设计?

我怎样才能知道 a 的所有类型Access?不仅是包装访问的类型,还有包装访问的类型。

编辑: 我的一个需求是:Access按类型过滤 es 集合 -ÌnAllowedAccess,InDeniedAccess,OutAllowedAccess,OutDeniedAccess,MismatchAccess(这是一个装饰器)和我可能开发的其他类型的装饰器

4

2 回答 2

0

避免类型检查通常是最好的做事方式。不幸的是,您没有提供足够的上下文来说明您将如何使用您的类,因此我可以举例说明如何使用多态性并避免它。

添加类型检查将限制系统增长的能力,因为随着新类的添加,这些类型需要包含在类型检查中。有时这会导致错误,因为您的代码可以假设类的数量或其类型。这是一个例子:

注意:我只是为了说明目的而编造这个。这不是关于必须代表你的逻辑或类似的东西。

public void someMethod(Access access) {

    if(access instance of InAccess) { 
        InAccess inAccess = (InAccess)access;
    }
    else {
        OutAccess outAccess = (OutAccess)access;
    }
}

当我们启动时,我们的系统有两个继承自Access. 假设我们将另一个添加Access class到我们的系统中。这段代码会在 else 上崩溃,因为我们可能会传递新的第三种访问类型并且强制转换不会成功。

当然,情况并非总是如此。有时,您拥有的课程数量不会增长太多。您可以预测所有类型。

当然,由于所有事情都可能发生在编程中,所以有时您确实需要知道您正在使用的对象的类型。

假设您的系统确实需要知道对象的类型。这里有两个解决方案:

  1. 添加一个将代表您拥有的所有类型的枚举。

public enum AccessType { InAccessAllowed, InAccessDenied, OutAccessDenied, // other types }

public interface Access {
   AccessType getType();
   // other stuff
}

这样,您将使用enum AccessType类型转换而不是类型转换。

  1. 使用接口。

不是使用类,而是为每种类型的Access. 然后您将检查接口而不是类。这样,您的装饰器可以实现与它所装饰的类相同的接口。

public interface InAllowedAccess { }

public class InAllowedAccessImp implements InAllowedAccess { }

public class InAllowedAccessDecorator implements InAllowedAccess { }

我只是不想给出替代​​实现的示例。由于您的描述中缺少上下文,我将尝试猜测您将如何使用您的类并向它们添加行为。这只是一个想法,仅此而已。

假设您的系统授予用户访问权限。可以为用户提供 In 和 Out 访问权限,并且系统的某些部分需要询问是否授予或拒绝特定用户的访问权限,以便它可以执行特定的逻辑。

如果您没有任何与您相关的行为,Access classes则可以将其用作描述符,该描述符将携带其他类完成工作所需的信息。

public enum PortType { In, Out }
public enum Permissions { Allowed, Denied }

public class Access {
    private PortType mPortType;
    private Permissions mPermissions;

    public Access(PortType portType, Permissons permissions) {
        mPortType = portType;
        mPermissions = permissions;
    }

    public PortType getType() { return mPortType; }
    public Permissions getPermissions() { return mPermissions; }
}

如果你确实有行为,那么你可以使用多态性。定义你的行为Access interface并让实现这个接口的类定义行为。

假设我们有消息系统,用户可以接收(输入)和发送(输出)消息。这些消息通过一个渠道。这些通道将接受或拒绝消息。这是一种可以使用多态性而不是类型检查的方法。

public interface MessageChannel {

    public bool canSendMessages(); // out
    public bool canReceiveMessages(); // in

    public void receiveMessage(Message m);
    public void sendMessage(Message m);
}

public class InMessageChannel implements MessageChannel {

    // out messaging is not allowed, cannot send
    public bool canSendMessages() { return false; } 

    // In messaging allowed, can receive
    public bool canReceiveMessages() { return true; } 

    public void sendMessage(Message m) {
        throw new SendingMessagesIsNotAllowd();
    }
    public void receiveMessage(Message m); { 
        // do something with the mssage
    }
}

public class OutMessageChannel implements MessageChannel {

    // out messaging allowed
    public bool canSendMessages() { return true; } 

    // In messaging not allowed
    public bool canReceiveMessages() { return false; } 

    public void sendMessage(Message m) {
        // send the message
    }

    public void receiveMessage(Message m); { 
        throw new ReceivingMessagesIsNotAllowd();
    }
}

如您所见,每个MessageCahnnel都有与之相关的行为。如果允许或不允许,它可以发送接收消息。这样其他使用 的类MessageChannel就不必进行类型转换了。

于 2019-06-01T19:08:16.220 回答
0

我想过在 Access 类中实现 isInstanceofInAllowed()、isInstanceofOutAllowed()、isInstanceofInDenied() 和 isinstanceofOutDenied() 等方法,但似乎不是一个好的解决方案,我不知道......

你说的对。这是一个糟糕的解决方案。接口通常属于软件中抽象程度较高的层,因此其方法列表应该是稳定的。如果你把上面这样的一堆方法放到Access接口中,接口会很不稳定,因为将来你很可能会在里面添加更多这样的方法。

解决您的问题的最简单方法是(仅一次)添加一个名为接口core()的新方法。Access每个装饰器只是通过返回包装/核心对象来实现此方法。

interface Access {
    ...
    Access core();
}

Access a = ...
if (a.core() instanceof ...
于 2019-06-02T04:37:55.287 回答