设计模式以保持行为独特但根据接口有所不同

Design pattern to keep behavior unique but make differ according to interfaces

我正在寻找我刚刚制作的设计模式的名称,以及它是否是一个好的。

所以基本上我是在寻找一种方法来在 Actor class 的子class 之间保持主要行为,根据子class 的子接口划分子行为。 =35=] 实现。

这里有一个简化的例子,可以让我的观点更容易理解...

演员 Class :

public abstract class Actor implements FirstSubBehavior, SecondSubBehavior/*, MoreBehaviors...*/{
    
    public final void mainBehavior(){
        
        doFirstSubBehavior();
        doSecondSubBehavior();
        /* ... */
        //doNthSubBehavior();
        System.out.println();
        
    }
    
}

一个 FirstSubBehavior 接口:

public interface FirstSubBehavior{
    
    public void doFirstSubBehavior();
    
    public interface FirstWay extends FirstSubBehavior{
        
        public default void doFirstSubBehavior(){
            
            System.out.println("I'm doing the 1st sub-behavior using the 1st way.");
            
        }
        
    }
    
    public interface SecondWay extends FirstSubBehavior{
        
        public default void doFirstSubBehavior(){
            
            System.out.println("I'm doing the 1st sub-behavior using the 2nd way.");
            
        }
        
    }
    
    /* ... */
    
    public interface NthWay extends FirstSubBehavior{
        
        public default void doFirstSubBehavior(){
            
            System.out.println("I'm doing the 1st sub-behavior using the Nth way.");
            
        }
        
    }
    
}

一个 SecondSubBehavior 接口:

public interface SecondSubBehavior{
    
    public void doSecondSubBehavior();
    
    public interface FirstWay extends SecondSubBehavior{
        
        public default void doSecondSubBehavior(){
            
            System.out.println("I'm doing the 2nd sub-behavior using the 1st way.");
            
        }
        
    }
    
    public interface SecondWay extends SecondSubBehavior{
        
        public default void doSecondSubBehavior(){
            
            System.out.println("I'm doing the 2nd sub-behavior using the 2nd way.");
            
        }
        
    }
    
    /* ... */
    
    public interface NthWay extends SecondSubBehavior{
        
        public default void doSecondSubBehavior(){
            
            System.out.println("I'm doing the 2nd sub-behavior using the Nth way.");
            
        }
        
    }
    
}

还有一个 Main Class 来测试它:

public class Main{
    
    public static void main(String[] args){
        
        class Actor1 extends Actor implements FirstSubBehavior.FirstWay, SecondSubBehavior.FirstWay {}
        
        new Actor1().mainBehavior();
        
        class Actor2 extends Actor implements FirstSubBehavior.FirstWay, SecondSubBehavior.NthWay {}
        
        new Actor2().mainBehavior();
        
    }
    
}

这会产生以下输出:

I'm doing the 1st sub-behavior using the 1st way.
I'm doing the 2nd sub-behavior using the 1st way.

I'm doing the 1st sub-behavior using the 1st way.
I'm doing the 2nd sub-behavior using the Nth way.

所以 main 很重要,在那里你可以看到我想如何使用我的 Actor class:我想对我所有的 subclasses 的主要行为进行一次编码,然后能够根据它实现的默认子行为使其不同。

希望我说清楚了,如果不是我可以重新表述。

仔细阅读Liskov substitute。所以你的模式破坏了坚定的行为。

出现的问题:

  • 如果两个步骤之间的状态转换需要是原子的/事务性的怎么办? (全部或none)
  • 如果在执行已获取资源的步骤时抛出 RuntimeException 怎么办?
  • 如果链下的条件需要链上的改变怎么办?

这样的链接模式已经存在,但作为有效的 Liskov 替代品:

  • Servlets有一个过滤链,通过接口明确限制。状态更改是可能的,例如会话内存或请求包装。
  • 验证器只收集错误或快速失败,验证对象的状态没有变化。 (这更像是一个通用契约,因为除非验证真正的不可变,否则没有什么可以阻止验证器实例也调用设置方法。)
  • 通过命令进行状态转换。每个命令都绑定一个更改,可以完成、撤消或重新完成。命令序列形成一个链来改变一个或多个实体。命令永远不会改变,也不会改变/命令本身是不可变的。
  • 策略是一种更好的模式,在一侧有一个契约和多种实现。例如 XML-readers 或 writers 的构造取决于生成通用接口的类路径。

我总是更喜欢策略方法,但也喜欢一个建议的评论:为了特定的目的。您需要从各种资源中读取字符串行或一组专用记录:每种资源类型都有一个策略。合约表示为如下接口:

public interface LineReader {
  List<String> readAll();
}

这可以通过 FileLineReader、StreamLineReader 和/或 UserInputReader 来实现。然后将其链接为:

// already unmodifiable, factory classes/ methods
final List<Command> commandChain=Commands.forUsecase(UseCase.READ_TRANSFORM_PERSIST);

final Processor p=new Processor();

// only proceeds upon valid records
p.setPrecondition(Validators.fixedLengthRecordStyle());
// set of commands doing something with the context and data
p.setCommandChain(commandChain);
// Where to take data from
p.setSource(new FileLineReader(new File("/tmp/input.csv", LineFilters.skipEmptyLinesAndComments())));

// now there's a result
final ProcessingResult pr = p.process();

if (!pr.isValid()) {
  // print validation errors and exit
}

if (!pr.isSuccessful()) {
  // print processing errors and exit
}

// print success and exit.
System.printf("Read %d records, stored %d records, %d were duplicates", 
  pr.getNumberOfRecords(), pr.getNumberOfSaved(), 
  pr.getNumberOfSkipped());