我很好奇:使用Java 8,并且可以在接口中添加实现(有点像Scala traits),是否可以像在Scala中一样实现cake pattern?
如果可以,能否提供一段代码片段?
如果可以,能否提供一段代码片段?
在参考其他答案的启发下,我想出了以下(粗略的)类层次结构,类似于Scala中的cake pattern:
class A {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,截至2013年1月9日。
那么,Java 8能够像蛋糕一样使用模式吗?可以。
它是否像Scala那样简洁,或者像Java中其他模式(例如依赖注入)那样有效?可能不是,上面的示例需要大量文件,而且不像Scala那么简洁。
总之:
val
和var
。this.getClass()
来发现我们的类型。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"
Nested classes are automatically static. This is inherently 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();
So, apparently, are nested interfaces, although it's harder to coax out the error messages:
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.
因此,如果没有实例成员类,您就没有路径相关类型,这对于蛋糕模式基本上是必要的。所以至少可以说,不是以直接的方式实现。
this
和this.getClass()
,并且可以通过弱引用映射添加额外的状态。然而,在日志记录示例中,这不是Java的方式;使用实例字段final Logger logger=Logger.of(this);
来实现混合效果的简单/旧解决方案没有任何问题。 - irreputable