2013-01-10 70 views

回答

23

與其他答案啓發我想出了以下(粗糙)類層次結構類似於在斯卡拉蛋糕模式:

interface UserRepository { 
    String authenticate(String username, String password); 
} 

interface UserRepositoryComponent { 
    UserRepository getUserRepository(); 
} 

interface UserServiceComponent extends UserRepositoryComponent { 
    default UserService getUserService() { 
     return new UserService(getUserRepository()); 
    } 
} 

class UserService { 
    private final UserRepository repository; 

    UserService(UserRepository repository) { 
     this.repository = repository; 
    } 

    String authenticate(String username, String password) { 
     return repository.authenticate(username, password); 
    } 
} 

interface LocalUserRepositoryComponent extends UserRepositoryComponent { 
    default UserRepository getUserRepository() { 
     return new UserRepository() { 
      public String authenticate(String username, String password) { 
       return "LocalAuthed"; 
      } 
     }; 
    } 
} 

interface MongoUserRepositoryComponent extends UserRepositoryComponent { 
    default UserRepository getUserRepository() { 
     return new UserRepository() { 
      public String authenticate(String username, String password) { 
       return "MongoAuthed"; 
      } 
     }; 
    } 
} 

class LocalApp implements UserServiceComponent, LocalUserRepositoryComponent {} 
class MongoApp implements UserServiceComponent, MongoUserRepositoryComponent {} 

關於Java 8以上編譯爲1月9日2013年。


所以,可以的Java 8做cake- 模式? 是的。

它和Scala一樣簡潔,還是和Java中的其他模式(即依賴注入)一樣有效? 可能不是,上面的草圖需要大量的文件,並不像Scala那樣簡潔。

總結:

  • 自類型(作爲所需的餅圖案)可以通過延伸的基本接口我們期望進行仿真。
  • 接口不能有內部類(如@Owen所指出的),所以我們可以使用匿名類。
  • valvar可以通過使用靜態哈希映射(和延遲初始化)或類的客戶端簡單地將值存儲在其側面(如UserService)仿效。
  • 我們可以通過使用默認界面方法中的this.getClass()來發現我們的類型。
  • @Owen指出,使用接口不可能使用路徑依賴的類型,所以一個完整的蛋糕模式本質上是不可能的。但是,上面顯示可以將其用於依賴注入。
+0

您應該能夠訪問'this'和'this.getClass()'的默認方法的身體,你可以通過一個微弱的標識映射添加額外的狀態。然而在日誌記錄的例子中,它不是java的方式;添加一個實例字段「最終Logger記錄器= Logger.of(this);'來實現mixin效果的簡單/舊解決方案沒有任何問題。 – irreputable

+0

你是對的,更新了帖子以反映這一點。 –

+0

謝謝,很好的回答! –

2

一些實驗表明NO:

  • 嵌套類是自動靜態的。這本質上是uncakelike:

    interface Car { 
        class Engine { } 
    } 
    
    // ... 
        Car car = new Car() { }; 
        Car.Engine e = car.new Engine(); 
    
    error: qualified new of static class 
        Car.Engine e = car.new Engine(); 
    
  • 所以,很明顯,是嵌套的接口,雖然它很難哄出來的錯誤信息:

    interface Car { 
        interface Engine { } 
    } 
    
    // ... 
        Car car = new Car() { }; 
        class Yo implements car.Engine { 
        } 
    
    error: package car does not exist 
         class Yo implements car.Engine { 
    
    // ... 
    
    class Yo implements Car.Engine { 
    }                          
    
    
    // compiles ok. 
    

因此,沒有實例成員類,你做沒有路徑相關的類型,這對於蛋糕模式來說基本上是必需的。所以至少,不,不是以直接的方式, 這是不可能的。

2

也許你可以做這樣的事情在Java中8

interface DataSource 
{ 
    String lookup(long id); 
} 

interface RealDataSource extends DataSource 
{ 
    default String lookup(long id){ return "real#"+id; } 
} 

interface TestDataSource extends DataSource 
{ 
    default String lookup(long id){ return "test#"+id; } 
} 

abstract class App implements DataSource 
{ 
    void run(){ print("data is " + lookup(42)); } 
} 


class RealApp extends App implements RealDataSource {} 

new RealApp().run(); // prints "data is real#42" 


class TestApp extends App implements TestDataSource {} 

new TestApp().run(); // prints "data is test#42" 

但它絕不比平原/老辦法

interface DataSource 
{ 
    String lookup(long id); 
} 

class RealDataSource implements DataSource 
{ 
    String lookup(long id){ return "real#"+id; } 
} 

class TestDataSource implements DataSource 
{ 
    String lookup(long id){ return "test#"+id; } 
} 

class App 
{ 
    final DataSource ds; 
    App(DataSource ds){ this.ds=ds; } 

    void run(){ print("data is " + ds.lookup(42)); } 
} 


new App(new RealDataSource()).run(); // prints "data is real#42" 


new App(new TestDataSource()).run(); // prints "data is test#42" 
+0

你的第一示例編譯和運行如預期中的Java 8. –

1

忽略的Java 8可以將這些新功能更好理論上使用編譯時間AspectJ ITDs在Java 5及更高版本中執行Cake Pattern。

AspectJ DTO's allow you to make Mixins。唯一令人討厭的是你將不得不製作兩個工件:方面(ITD)和界面。然而,ITD允許你做一些瘋狂的事情,比如爲實現接口的類添加註釋。

3

我做了一個小的證明,在概念上這家最近。你可以看到這裏的博客文章:http://thoredge.blogspot.no/2013/01/cake-pattern-in-jdk8-evolve-beyond.html和github回購這裏:https://github.com/thoraage/cake-db-jdk8

基本上你可以做到這一點,但你至少面臨兩個障礙,使它比斯卡拉更光滑。首先,Scala特徵可以具有狀態,而Java的接口不能。許多模塊需要狀態。這可以通過創建一個通用的狀態組件來保存這些信息來解決,但這需要在一個類中。至少部分。第二個問題是,接口中的嵌套類更類似於類中的靜態嵌套類。所以你不能直接從模塊類訪問接口方法。默認的接口方法可以訪問這個範圍,並且可以將它添加到模塊類的構造函數中。

+0

狀態可以通過使用靜態身份映射,映射從(例如 - >值)來處理(在很不雅方式)對於每個字段,然後懶惰地在初始化它每個領域的獲得者。 –