有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java获取装饰器对象的所有类型:包装对象的类型和包装对象的类型

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

design

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

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类型,但我真正想知道的是一些Access的所有类型在这种情况下,wrapperAccess不仅是类型MismatchAccess,而且也是类型InAllowedAccess

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

否则,我应该为每4种类型InAllowedMismatchAccessOutAllowedMismatchAccessInDeniedMismatchAccessOutDeniedMismatchAccess创建一个大的层次结构树吗?然后,当我开发另一个装饰师时

还是有其他更好的设计

我如何知道Access的所有类型?不仅是包装访问的类型,而且是包装访问的类型

编辑: 我的需求之一是:按类型过滤Access个集合-ÌnAllowedAccessInDeniedAccessOutAllowedAccessOutDeniedAccessMismatchAccess(这是一个装饰器)和我可能开发的其他类型的装饰器


共 (2) 个答案

  1. # 1 楼答案

    避免类型检查通常是最好的方法。不幸的是,您没有给出足够的上下文来说明如何使用类,所以我可以举一个例子说明如何使用多态性并避免它

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

    注:我只是为了说明而编造的。这并不是说你必须表达自己的逻辑或诸如此类的东西

    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 { }
    

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

    假设您的系统授予用户访问权限。用户可以被授予进出权限,系统的某些部分需要询问特定用户是否被授予或拒绝访问权限,以便它可以执行特定的逻辑

    如果你没有任何与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的类就不必进行类型转换

  2. # 2 楼答案

    I thought about implementing methods like isInstanceofInAllowed(), isInstanceofOutAllowed(), isInstanceofInDenied() and isinstanceofOutDeniedd() in Access classes but don't seems a good solution, I don't know...

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

    解决问题的最简单方法是(仅一次)向Access接口添加一个名为core()的新方法。每个decorator都只是通过返回wrapped/core对象来实现这个方法

    interface Access {
        ...
        Access core();
    }
    
    Access a = ...
    if (a.core() instanceof ...