对象中仅 return 某些 LDAP 属性的设计模式
Design Pattern to only return certain LDAP attributes in an object
假设我有以下 class,有许多实例变量和相应的 getter 和 setter:
public class Foo {
private String a;
private int b;
...
private List<String> z;
public String getA() { return a; }
public void setA(String a) { this.a = a; }
public int getB() { return b; }
public void setB(int b) { this.b = b; }
...
}
还有另一个 class 填充值,它是资源密集型的:
public class MyService {
public Foo retrieveFoo() {
// call some resource intensive code to retrieve the values
String a = getTheString();
int b = getTheInt();
List<String> z = getTheList();
Foo f = new Foo();
f.setA(a);
f.setB(b);
...
f.setZ(z);
return f;
}
}
我有多个客户想要使用上述 class 的实例,但有些客户只对获取变量值的一小部分而不是全部感兴趣:
public class ClientA {
private MyService service;
public void doSomething() {
Foo f = service.retrieveFoo();
String a = f.getA();
int b = f.getB();
// not interested in anything else
}
}
public class ClientB {
private MyService service;
public void doSomething() {
Foo f = service.retrieveFoo();
List<String> z = f.getZ();
// not interested in anything else
}
}
我可以做的一件事是让客户端告诉 MyService 只检索它感兴趣的值。像这样:
public class ClientA {
private MyService service;
public void doSomething() {
// the Service would only retrieve a and b, which
// means all other variables would be set to Null
Foo f = service.retrieveFoo(Arrays.asList("a","b"));
String a = f.getA();
int b = f.getB();
// not interested in anything else
}
}
但是,这似乎是错误的,因为其他值将为空。有没有更好的设计方法?
编辑:
更具体地说,我正在处理 LDAP 系统中的用户属性。我不想拥有一个人的所有属性的 'God object',我只想提取每个用例所需的子集。例如,一个应用程序可能需要 uid 和 fullName;另一个可能需要 uid、phone 号码、组等
谢谢。
您需要组合使用单例模式和外观设计模式。
Singleton 只在 MyService
中保留一份 Foo
对象。人脸将只提供 getA()
、getB()
等 ... 方法,用于每个所需的数据组合。
Client
class 将调用外观以获取所需信息。事实上,你可以让你的 My Service
同时作为单例和门面来解决这个问题。
class MyService{
private static Foo foo;
private MyService(){}
static{
foo = initFoo(); // initialize the Foo object
}
// Now provide the facade api for each required combination
static getA(){return foo.getA();}
static getB(){return food.getB();}
// etc ....
}
如果您有 Foo
的多个实现(或)版本,则创建工厂以在 Facade
.
中检索正确的版本
您可以将接口用作 Facades 和 "Adapters"(它们实际上不是适配器,只是专门的构建器)来检索数据?例如
interface IFooA {
A getA();
}
interface IFooB {
B getB();
}
public class Foo implements IFooA, IFooB {
// ....
}
public class MyService {
// code not optimized for brevity!
public IFooA retrieveFooA() {
return new IFooAAdapter().getOnlyIFooASubset();
}
public IFooB retrieveFooB() {
return new IFooBAdapter().getOnlyIFooBSubset();
}
一个最简单的解决方案是使用不同的 getter 集声明多个接口,在您的 class 中实现所有接口,并让不同的客户端使用不同的接口。
例如
interface A {
String getA();
}
interface B {
String getB();
}
class MyClass implements A, B {
String getA() {...}
String getB() {...}
}
现在客户端A使用接口A只能调用getA()
,客户端B使用接口B只能调用getB()
。
如果某些客户端 C 必须同时与 A 和 B 一起操作,您可以:
1.让它访问两个接口
2.直接访问MyClass
3. 定义扩展A 和B 的其他接口C,以便客户端C 可以使用它。
显然这个解决方案不是通用的,在某些情况下可能需要定义很多接口。
如果您想灵活地决定客户端可以在运行时访问的功能集,您可以使用接口,但不在您的 class 中实现它们,而是使用动态代理来包装您的 class 并公开所需的接口。但是,由于反射调用,此解决方案的工作速度会变慢。
我可以考虑其他解决方案,但我希望这里已经写的对你来说足够好。
这闻起来像上帝 Class,或者充其量是 class,但内聚力很差。 Classes 应该具有简单的设计和凝聚力。凝聚力意味着有一个明显的主题(由名称给出)并且方法支持该主题。当你有一个名为 "Utilities" 的 class 时,它是 class 内聚性差的一个很好的例子(很多方法和属性都塞在那里,因为没有更好的地方来放置它们) .
您可以 refactor the God class 或根据客户的需要分解对象并使用组合 classes。
如果您发布 class 的真实姓名(而不是 Foo 等),我们将能够为您提供更好的设计思路。这些细节很重要。
假设我有以下 class,有许多实例变量和相应的 getter 和 setter:
public class Foo {
private String a;
private int b;
...
private List<String> z;
public String getA() { return a; }
public void setA(String a) { this.a = a; }
public int getB() { return b; }
public void setB(int b) { this.b = b; }
...
}
还有另一个 class 填充值,它是资源密集型的:
public class MyService {
public Foo retrieveFoo() {
// call some resource intensive code to retrieve the values
String a = getTheString();
int b = getTheInt();
List<String> z = getTheList();
Foo f = new Foo();
f.setA(a);
f.setB(b);
...
f.setZ(z);
return f;
}
}
我有多个客户想要使用上述 class 的实例,但有些客户只对获取变量值的一小部分而不是全部感兴趣:
public class ClientA {
private MyService service;
public void doSomething() {
Foo f = service.retrieveFoo();
String a = f.getA();
int b = f.getB();
// not interested in anything else
}
}
public class ClientB {
private MyService service;
public void doSomething() {
Foo f = service.retrieveFoo();
List<String> z = f.getZ();
// not interested in anything else
}
}
我可以做的一件事是让客户端告诉 MyService 只检索它感兴趣的值。像这样:
public class ClientA {
private MyService service;
public void doSomething() {
// the Service would only retrieve a and b, which
// means all other variables would be set to Null
Foo f = service.retrieveFoo(Arrays.asList("a","b"));
String a = f.getA();
int b = f.getB();
// not interested in anything else
}
}
但是,这似乎是错误的,因为其他值将为空。有没有更好的设计方法?
编辑:
更具体地说,我正在处理 LDAP 系统中的用户属性。我不想拥有一个人的所有属性的 'God object',我只想提取每个用例所需的子集。例如,一个应用程序可能需要 uid 和 fullName;另一个可能需要 uid、phone 号码、组等
谢谢。
您需要组合使用单例模式和外观设计模式。
Singleton 只在 MyService
中保留一份 Foo
对象。人脸将只提供 getA()
、getB()
等 ... 方法,用于每个所需的数据组合。
Client
class 将调用外观以获取所需信息。事实上,你可以让你的 My Service
同时作为单例和门面来解决这个问题。
class MyService{
private static Foo foo;
private MyService(){}
static{
foo = initFoo(); // initialize the Foo object
}
// Now provide the facade api for each required combination
static getA(){return foo.getA();}
static getB(){return food.getB();}
// etc ....
}
如果您有 Foo
的多个实现(或)版本,则创建工厂以在 Facade
.
您可以将接口用作 Facades 和 "Adapters"(它们实际上不是适配器,只是专门的构建器)来检索数据?例如
interface IFooA {
A getA();
}
interface IFooB {
B getB();
}
public class Foo implements IFooA, IFooB {
// ....
}
public class MyService {
// code not optimized for brevity!
public IFooA retrieveFooA() {
return new IFooAAdapter().getOnlyIFooASubset();
}
public IFooB retrieveFooB() {
return new IFooBAdapter().getOnlyIFooBSubset();
}
一个最简单的解决方案是使用不同的 getter 集声明多个接口,在您的 class 中实现所有接口,并让不同的客户端使用不同的接口。
例如
interface A {
String getA();
}
interface B {
String getB();
}
class MyClass implements A, B {
String getA() {...}
String getB() {...}
}
现在客户端A使用接口A只能调用getA()
,客户端B使用接口B只能调用getB()
。
如果某些客户端 C 必须同时与 A 和 B 一起操作,您可以: 1.让它访问两个接口 2.直接访问MyClass 3. 定义扩展A 和B 的其他接口C,以便客户端C 可以使用它。
显然这个解决方案不是通用的,在某些情况下可能需要定义很多接口。
如果您想灵活地决定客户端可以在运行时访问的功能集,您可以使用接口,但不在您的 class 中实现它们,而是使用动态代理来包装您的 class 并公开所需的接口。但是,由于反射调用,此解决方案的工作速度会变慢。
我可以考虑其他解决方案,但我希望这里已经写的对你来说足够好。
这闻起来像上帝 Class,或者充其量是 class,但内聚力很差。 Classes 应该具有简单的设计和凝聚力。凝聚力意味着有一个明显的主题(由名称给出)并且方法支持该主题。当你有一个名为 "Utilities" 的 class 时,它是 class 内聚性差的一个很好的例子(很多方法和属性都塞在那里,因为没有更好的地方来放置它们) .
您可以 refactor the God class 或根据客户的需要分解对象并使用组合 classes。
如果您发布 class 的真实姓名(而不是 Foo 等),我们将能够为您提供更好的设计思路。这些细节很重要。