【问题标题】:Java/Patterns for hiding methods from third party classes用于向第三方类隐藏方法的 Java/模式
【发布时间】:2010-07-06 06:17:10
【问题描述】:

我有一个 A 类,它有一系列处理程序,例如公共无效句柄Ev1(),公共无效句柄Ev2()等。 当事件发生时,B 类中的另一个线程从 A 类调用对应的处理程序(B 类具有对 A 类的一种观察者可观察的引用)。 在A类的对应方法中对事件的处理中,A最终将一个事件引发到一个eventListener(C类不是我创建的)。 我的问题如下:是否有一种模式可以用来从充当 eventListeners 的类中“隐藏”类 A 的处理方法(不是由我实现的),并且仅对类 B(其中我执行)?

我正在编辑我原来的问题。 我的 Csystem 类有很多方法和我正在谈论的处理程序

public class Csystem()
{

   private AListener listener;//implements an event listener (the class C in my question)

//some methods here
 public void handleEventIncoming(Event e){
//Do some logic here
  listener.raiseEvent(e);
 }
 public void handleEventOutgoing(Event e); etc


}

CSystem 是一个类,它本质上是其他组件的其他开发人员对我的代码的接口。其他一些开发人员将编写他自己版本的 AListener 类(A 类)并在他的代码中使用 Csystem。每当某处发生事件(例如,网络中的消息到达)时,B 类都会将该事件传递给 CSystem 的事件处理程序

public class Dispatch{
//This is class B
 private CSystem s;

 private void event_occured(Event e)
 {
    s.handleEventIncoming(e);
 }
}   

} 我的问题是 Dispatch 类(由我实现)和 AListener 类都“看到”了 CSystem 的相同接口。我希望实现 AListener 的开发人员能够看到 CSystem 的不同视图并“看到”并且能够仅使用公共方法。我认为查看某人实际上无法使用的方法并不是一个好主意(处理程序对于仅由调度程序使用是有意义的)是否有实现此目的的模式?

谢谢!

【问题讨论】:

    标签: java design-patterns oop


    【解决方案1】:

    使用接口。 B 与 A 的关系仅通过 B 定义和 A 实现的接口。

    所以从 B 的角度来看,它甚至不导入 A,或者在编译时访问 A 的定义。

    针对问题进行了编辑。

    我相信你有一个 C 类

    预先存在的,您无法更改的,某些包 x.y 中的代码;

    Class CEvent {
       // some event definition
    };
    
    Class C {
        public void callWhenitHappens(CEvent theEvent) {
           // do something
        }
    }
    

    --- 你写的代码---

    package p.q;
    public Class A implements BEventInterface {
    
       public void bEventHappened( BEvent theBEvent ){
           // make a C event
           myC.callWhenitHappens(theCEvent);
       }
    
    }
    

    您担心的是,任何人,甚至包括 C 在内都可以调用 bEventHappened() 方法。

    我的感觉是你担心一个不太可能的问题。为什么有人会麻烦地创建一个 A 对象并这样做?不过也有一些可能性:

    1)。如果 A 和 B 在同一个包中,不要公开 A 和它的方法。只有 B 需要查看它们,因此在包范围内这将起作用。

    2)。匿名内部类。请注意,A ia 类没有公共方法,因此 C 不能使用它,而 B 在它可以使用的匿名内部类上具有公共方法。

    package p.q;
    
    import p.q.B.BEvent;
    import x.y.z.C.CEvent;
    import x.y.z.C;
    
    public class A  {
    
    // anonymous class implementing required interface
    private BListener myFacade = new BListener(){
        @Override
        public void listen(BEvent event) {
            bEventHappened(event);          
        }       
    };
    
    private B myB;
    private C myC;
    
    A() {
        myC = new C();
        myB = new B();
        myB.registerListener(myFacade);
    }
    
    private void bEventHappened( BEvent theBEvent ){
           myC.callWhenitHappens(myC.new CEvent() );
    }
    }
    

    B 类和 C 类看起来像:

    package p.q;
    
    public class B {
    
    public class BEvent {
        public String what;
    }
    
    private BListener myListener;
    
    private void fireEvent(){
        myListener.listen(new BEvent());
    }
    
    public void registerListener(BListener listener){
        myListener = listener;
    }
    
    }
    

    package x.y.z;
    
    public class C {
    public class CEvent {
        public String what;
    }
    
    public void callWhenitHappens(CEvent event){
        //e3c
    }
    

    }

    【讨论】:

    • 嗨,您的意思是以下?公共类 B{ 接口处理程序 { public void handleEv1();公共无效句柄Ev1(); } 等 } A 类实现 Handlers{ public void handleEv1();公共无效句柄Ev1();等 } 但是这种设计仍然不是 C 仍然可以访问处理程序,因为它们是公共的?还是我误解了你的意思?
    • 但是你的A向C发送了一个事件,C对A一无所知,它在你写A之前很久就编译好了,C中没有代码知道anA.myMethod( )。
    • 感谢您的回复。对我来说问题如下(可能是我的想法是错误的):我有 A 类,它作为 B 类和 C 类之间的边界。A 类将 C 类注册为监听器。 B类,当事件发生时,调用A的handlerMethods,该方法做一些处理,将事件引发给C。但是A的handler方法是公共的。 A 用作我未实现的代码的接口,并且如果处理程序方法具有私有范围,以便 C 例如不能调用 A 类的处理程序,我更喜欢它。那么我应该如何重新设计我的类来实现这一点?谢谢!
    • C 现在是什么样子的?我将扩展我的答案以显示我期望的情况。但是,也许你有一些不同的情况。因此,请更详细地扩展您的问题。
    【解决方案2】:

    您似乎有一个具有多个职责的接口的类。这是一件坏事。一个简单的方法是使用匿名内部类来实现回调接口。

    【讨论】:

    • 你能举个小例子来说明你的建议吗?
    【解决方案3】:

    您可以将 A 和 B 放在包 alpha 中,将 C 放在包 omega 中。 A 和 B 可以访问彼此的包私有成员,但 C 没有。你也应该使用像 djna 说的接口。

    package alpha ;
    public interface A { void doSomething ( ) ; }
    public interface B { }
    class AImpl implements A { ... void doSomethingPrivate ( ) { ... } }
    class BImpl implements B { AImpl a ; ... a.doSomethingPrivate ( ) ; }
    
    package omega ;
    public interface C { public void handle ( alpha.a a ) ; ... }
    

    【讨论】:

    • 放置同一个包解决了这个问题,但不幸的是我没有这个选项,因为我没有从头开始编码,这部分(包)已经存在
    【解决方案4】:

    你可以这样做:

    interface EventSource<T>{ 
        void addEventListener(T listener);
        void removeEventListener(T listener);
    }
    class B implements EventSource<SomethingListener>
    {
        A instA;
        ...
        public B(A instA)
        {
            this.instA = instA;
            instA.installEventSource(this);
            ...
        }
        ...
    } 
    class A
    {
        ...
        public void installEventSource(EventSource source)
        {
            source.addEventListener(listener);
        }
        public void uninstallEventSource(EventSource source)
        {
            source.removeEventListener(listener);
        }
    }
    

    【讨论】:

    • 所以在A类中,我有对B类的引用。当事件发生时,我会使用引用来调用相应的处理程序。但是该方法的可见性是什么?如果它是公开的,那么我仍然有同样的问题。对吗?
    • EventSource 是一个类。您可以使用插件系统(OSGI 或 Netbeans RCP)隐藏它,或者将其放在 internal 包下 - 一个常见的约定是不要在模块之外使用此类类。
    【解决方案5】:

    谢谢你的例子! 我不清楚它似乎。 我的 Csystem 类有很多方法和我正在谈论的处理程序

    public class Csystem()
    {
    
    private AListener listener;//implements an event listener (the class C in my question)
    
    //methods here
     public void handleEventIncoming(Event e){
    //Do some logic here
      listener.raiseEvent(e);
     }
     public void handleEventOutgoing(Event e); etc
    
    
    }
    

    CSystem 是一个类,它本质上是其他组件的其他开发人员对我的代码的接口。其他一些开发人员将编写他自己版本的 AListener 类(A 类)并在他的代码中使用 Csystem。 每当某处发生事件(例如,网络中的消息到达)时,B 类都会将该事件传递给 CSystem 的事件处理程序

    public class Dispatch{
    //This is class B
    private CSystem s;
    
     private void event_occured(Event e)
     {
        s.handleEventIncoming(e);
     }
    }   
    
    }
    

    我的问题是 Dispatch 类(由我实现)和 AListener 类都“看到”了 CSystem 的相同接口。我希望实现 AListener 的开发人员能够看到 CSystem 的不同视图并“看到”并且能够仅使用公共方法。我认为查看某人实际上无法使用的方法并不是一个好主意(处理程序仅由调度程序使用是有意义的) 有没有一种模式可以实现这一点?

    【讨论】:

    • 我无法编辑我原来的问题,所以我在这里扩展了我原来的问题的细节。对不起!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    相关资源
    最近更新 更多