【问题标题】:Parent wrapping child class method父包装子类方法
【发布时间】:2019-11-03 15:04:25
【问题描述】:

我让这些 Worker 类做一些工作:

class WorkerOne implements IWorker {
    @Override
    public doWork(Resource resource){
     // do some work
    }
}

我希望所有doWork() 方法都被同一个操作包装。

实现它的一种方法是创建一个抽象类,如下例所示:

abstract class WorkWrapper implements IWorker {
    @Override
    public doBetterWork(){
       Resource resource = // ...
       doWork(resource)
       resource .close();
    }
}


class WorkerOne extends WorkWrapper {

    protected doWork(Resource resource){
     // do some work
    }
}

并将 Worker 调用为:

WorkerOne worker = new WorkerOne();
worker.doBetterWork();

出于某些原因,我不喜欢使用继承。有没有更好的解决方案来做这种包装?

【问题讨论】:

    标签: java oop inheritance design-patterns abstract-class


    【解决方案1】:

    使用您可以在接口中定义的default 方法,您可以避免继承(extends)并坚持实现(implements):

    class WorkerOne implements IWorker {
        @Override
        public void doWork(Resource resource){
         // do some work
        }
    }
    
    public interface IWorker {
        void doWork(Resource resource);
    
        default void doBetterWork(){
           Resource resource = // ...
           doWork(resource)
           reource.close();
        }
    }
    

    并像以前一样使用它:

    IWorker worker = new WorkerOne();
    worker.doBetterWork(); 
    

    我希望所有 doWork() 方法都被同一个操作包装。

    就我个人而言,我不太喜欢在 API 方面公开两种方法的设计,而只有其中一种方法应该由类的客户端调用。这是误导。
    为了避免这种情况,我可能会使用组合和装饰器(不是传统的装饰器,因为两个 doWork() 方法之间的签名不同)。

    public interface IWorker {
        void doWork(Resource resource);
    }
    
    class WorkWrapper{
    
        private IWorker decorated;
        public WorkWrapper(IWorker decorated){
           this.decorated = decorated;
        }
        @Override
        public doWork(){
           Resource resource = // ...
           decorated.doWork(resource);
           reource.close();
        }
    }
    
    class FooWork implements IWorker {
    
        @Override
        public doWork(Resource resource){
              // do something...
        } 
     }
    

    现在没有歧义了:

    WorkWrapper worker = new WorkWrapper(new FooWork());
    worker.doWork(); // just this method is exposed now in WorkWrapper 
    

    你可以将它与工厂结合起来,让事情变得更简单,并从客户端隐藏实现细节:

    WorkWrapper worker = FooWork.createWrapperFor();
    worker.doWork(); 
    

    【讨论】:

      【解决方案2】:

      您所描述的情况似乎正是应用Template Method 设计模式的确切上下文。然而,这种模式确实需要继承。

      还有其他选择。但是,它非常适合您的要求,以至于我不敢称它们为“更好”的解决方案。

      继承的明显替代方案是组合。在您的情况下,这意味着应用 Strategy 模式。

      在应用此模式时,您的WorkWrapper 将成为上下文,而IWorker 将匹配抽象策略 的角色,其实现充当具体策略

      在代码中:

      class WorkWrapperContext {
          private IWorker strategy;
      
          WorkWrapperContext(IWorker strategy) { 
              this.strategy = strategy;
          }
      
          public void doBetterWorkOperation() {
              // do some stuff
              strategy.doWork();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-16
        • 2017-11-09
        • 2022-01-16
        • 2016-02-14
        相关资源
        最近更新 更多