- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有外观界面,用户可以在其中询问有关工程师的信息。该信息应以 JSON 形式传输,我们为其创建了 DTO。现在请记住,我有多个数据源可以向此 DTO 列表提供项目。
所以我相信现在我可以通过将数据源的处理程序添加到 myEngineerListDTO
来使用装饰模式类型 List<EngineerDTO>
。所以我的意思是所有数据源都有相同的 DTO。
下图显示了 VerticalScrollbar 和 HorizontalScrollBar 添加了不同的行为。这意味着他们向 WindowDecorator 接口(interface)添加行为。
我的问题,我的情况符合装饰器模式吗?我是否特别需要添加一个行为来使用此模式?还有其他模式适合我的情况吗?我已经考虑过责任链模式,但因为我不需要在任何给定时刻终止我的链,所以我认为装饰者模式可能会更好。
编辑:我的最终结果应该是:List<EngineersDTO>
来自所有数据源。我想添加此模式的原因是这样我可以轻松地在“管道”的其余部分后面添加另一个数据源。该数据源与其他数据源一样,将具有 addEngineersDTOToList
方法。
最佳答案
进一步说明如何 Chain-of-responsibility pattern我整理了一个小例子。我相信您应该能够调整此解决方案以满足您现实世界问题的需求。
<小时/>我们有一组未知的用户请求,其中包含要检索的属性的名称。有多个数据源,每个数据源都有不同数量的属性。我们希望搜索所有可能的数据源,直到发现请求中的所有属性。某些数据类型和数据源可能如下所示(请注意,为简洁起见,我使用 Lombok):
@lombok.Data
class FooBarData {
private final String foo;
private final String bar;
}
@lombok.Data
class FizzBuzzData {
private final String fizz;
private final String buzz;
}
class FooBarService {
public FooBarData invoke() {
System.out.println("This is an expensive FooBar call");
return new FooBarData("FOO", "BAR");
}
}
class FizzBuzzService {
public FizzBuzzData invoke() {
System.out.println("This is an expensive FizzBuzz call");
return new FizzBuzzData("FIZZ", "BUZZ");
}
}
我们的最终用户可能需要多种方法来解析数据。以下可能是有效的用户输入和预期响应:
// Input
"foobar", "foo", "fizz"
// Output
{
"foobar" : {
"foo" : "FOO",
"bar" : "BAR"
},
"foo" : "FOO",
"fizz" : "FIZZ"
}
我们的属性解析器的基本接口(interface)和简单的具体实现可能如下所示:
interface PropertyResolver {
Map<String, Object> resolve(List<String> properties);
}
class UnknownResolver implements PropertyResolver {
@Override
public Map<String, Object> resolve(List<String> properties) {
Map<String, Object> result = new HashMap<>();
for (String property : properties) {
result.put(property, "Unknown");
}
return result;
}
}
更好的解决方案可能是“责任链模式”,而不是使用普通的“装饰器模式”。此模式类似于装饰器模式,但是,链中的每个链接都可以处理该项目、忽略该项目或结束执行。这有助于决定是否需要进行调用,或者在请求的工作完成时终止链。与装饰器模式的另一个区别是,resolve 不会被每个具体类覆盖;我们的抽象类可以在需要时使用抽象方法调用子类。
回到手头的问题...对于每个解析器,我们需要两个组件。一种从远程服务获取数据的方法,以及一种从检索到的数据中提取所有必需属性的方法。为了获取数据,我们可以提供一个抽象方法。为了从获取的数据中提取属性,我们可以创建一个小接口(interface)并维护这些提取器的列表,因为可以从单个数据中提取多个属性:
interface PropertyExtractor<Data> {
Object extract(Data data);
}
abstract class PropertyResolverChain<Data> implements PropertyResolver {
private final Map<String, PropertyExtractor<Data>> extractors = new HashMap<>();
private final PropertyResolver successor;
protected PropertyResolverChain(PropertyResolver successor) {
this.successor = successor;
}
protected abstract Data getData();
protected final void setBinding(String property, PropertyExtractor<Data> extractor) {
extractors.put(property, extractor);
}
@Override
public Map<String, Object> resolve(List<String> properties) {
...
}
}
resolve
方法的基本思想是首先评估此 PropertyResolver
实例可以满足哪些属性
。如果有符合条件的属性,那么我们将使用 getData
获取数据。对于每个符合条件的属性,我们提取属性值并将其添加到结果映射中。每个无法解析的属性,后继者
将被请求解析该属性。如果所有属性都已解析,则执行链将结束。
@Override
public Map<String, Object> resolve(List<String> properties) {
Map<String, Object> result = new HashMap<>();
List<String> eligibleProperties = new ArrayList<>(properties);
eligibleProperties.retainAll(extractors.keySet());
if (!eligibleProperties.isEmpty()) {
Data data = getData();
for (String property : eligibleProperties) {
result.put(property, extractors.get(property).extract(data));
}
}
List<String> remainingProperties = new ArrayList<>(properties);
remainingProperties.removeAll(eligibleProperties);
if (!remainingProperties.isEmpty()) {
result.putAll(successor.resolve(remainingProperties));
}
return result;
}
当我们为 PropertyResolverChain
实现具体类时,我们需要实现 getData
方法并绑定(bind) PropertyExtractor
实例。这些绑定(bind)可以充当每个服务返回的数据的适配器。该数据可以遵循与服务返回的数据相同的结构,或者具有自定义架构。使用前面的 FooBarService 为例,我们的类可以像下面这样实现(请注意,我们可以有许多绑定(bind),从而返回相同的数据)。。 p>
class FooBarResolver extends PropertyResolverChain<FooBarData> {
private final FooBarService remoteService;
FooBarResolver(PropertyResolver successor, FooBarService remoteService) {
super(successor);
this.remoteService = remoteService;
// return the whole object
setBinding("foobar", data -> data);
// accept different spellings
setBinding("foo", data -> data.getFoo());
setBinding("bar", data -> data.getBar());
setBinding("FOO", data -> data.getFoo());
setBinding("__bar", data -> data.getBar());
// create new properties all together!!
setBinding("barfoo", data -> data.getBar() + data.getFoo());
}
@Override
protected FooBarData getData() {
return remoteService.invoke();
}
}
将它们放在一起,我们可以调用 Resolver
链,如下所示。我们可以观察到,仅当属性绑定(bind)到解析器时,昂贵的 getData
方法调用才对每个解析器执行一次,并且用户仅获取他们想要的确切字段。要求:
PropertyResolver resolver =
new FizzBuzzResolver(
new FooBarResolver(
new UnknownResolver(),
new FooBarService()),
new FizzBuzzService());
Map<String, Object> result = resolver.resolve(Arrays.asList(
"foobar", "foo", "__bar", "barfoo", "invalid", "fizz"));
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(result));
输出
This is an expensive FizzBuzz call
This is an expensive FooBar call
{
"foobar" : {
"foo" : "FOO",
"bar" : "BAR"
},
"__bar" : "BAR",
"barfoo" : "BARFOO",
"foo" : "FOO",
"invalid" : "Unknown",
"fizz" : "FIZZ"
}
关于java - 使用装饰器模式而不添加 "different"行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53300239/
我知道这类问题已经得到解答,但就我而言,我已经尝试了所有配置,但仍然不起作用。我需要对我的配置有一个新的看法(我确信我错过了一些东西)。两个附加程序都会记录所有级别 我想将所有包的信息 >= 记录到控
我正在对 Windows 移动设备上的代码性能进行一些基准测试,并注意到某些算法在某些主机上的表现明显更好,而在其他主机上则明显更差。当然,考虑到时钟速度的差异。 供引用的统计数据(所有结果均由同一个
我有一个程序可以计算多边形的面积和周长。程序还会确认面积和周长的计算结果是否与预期结果相同。 我不明白发生了什么,但确认面积和周长是否与预期相同的验证部分无法正常工作。 例如,我现在测试并在所有情况下
Codepen :(对于那些想直接进入的人来说,这是一个代码笔。在 Chrome 和 IE 中尝试一下,看看结果的不同) 我正在尝试使用 css3 转换/过渡,因为它们比 jquery 效果更流畅。
我有几个不同的正则表达式要在给定文本中匹配和替换。 regex1 :如果文本包含单词“Founder”,则将所有文本替换为首席执行官 正则表达式2:如果文本包含9位数字,则将其替换为NUM 我尝试使用
我编写了多线程应用程序,它从每个线程的数据库连接到一些电子邮件帐户。我知道 JavaMail 没有任何选项可以使用 SOCKS5 进行连接,因此我决定通过 System.setProperty 方法使
如您所见,这是我当前 Storyboard的不同设备预览。底部的透明绿色被另一个 View Controller 占用,但需要为每个不同的尺寸类固定间距。我尝试将 Storyboard 中的宽度和高度
我正在创建一个游戏,我需要能够改变玩家 Sprite 的速度。我认为最好的选择是通过重力影响 Sprite 。为了给用户运动的感觉,我希望背景以完全相同的速度向相反的方向移动。 我怎样才能给背景一个不
我正在查看BTrees库并注意到有多个 TreeSet (和其他)类,例如 BTrees.IOBTree.TreeSet BTrees.OOBTree.TreeSet BTrees.LFBTree.T
我有一个小型 C++ 库,必须为 armeabi 和 armeabi7a 编译。我还有一个非常大的 c++ 库,只需要为 armeabi 编译。现在正在为两种架构编译它们(使用 NDK),但这使我的
我需要根据站点的当前部分稍微更改主题。 似乎 MuiThemeProvider 只在加载时设置 muiTheme;但需要在 props 变化时更新。 如何做到这一点? 最佳答案 您可以尝试将主题放在包
如何创建两个每个都有自己的计数器的 lSTListing 环境? 如果我使用例如 \lstnewenvironment{algorithm}[2]{ \renewcommand\lstlist
我想使用 Travis-CI 和 Github 基于分支设置部署。 IE。 - 如果我们从 develop 构建- 然后执行 /deploy.rb使用 DEV 环境主机名,如果 master - 然后
我有一个带有数据验证的 WPF MVVM 数据表单窗口。很多控件都是文本框。目前,数据绑定(bind)触发器设置为默认值,即。 e.失去焦点。这意味着仅在可能完全填写字段时才对其进行验证。所以当删除一
我有许多应用程序的内容页面,并最终为每个内容页面编写了很多 View 模型。例如。如果我有一个包含项目组的列表,我将有一个 ShowAllViewModel并绑定(bind)到内容页面和列表中单个项目
我有一个通用 View 和 4 个其他 View 。我在通用 View 中使用 Bootstrap 选项卡(导航选项卡)。我希望其他 4 个 View 成为通用 View 中 4 个选项卡的内容。由于
我希望针对 Maven 发布插件的不同目标有不同的配置选项。故事是这样的: 我正在将 Git 用于 SCM。我希望release:prepare插件在本地完成所有操作,并让release:perfor
我正在为一个项目使用AbstractTableModel制作一个自定义TableModel,并且我需要找到一种方法让复选框显示在某些行上,而不是其他行上。我已经实现了 getColumn 方法,但我希
摘自《Javascript 忍者的 secret 》一书: EVENTS ARE ASYNCHRONOUS Events, when they happen, can occur at unpredi
我正在尝试配置我的第一个 GWT 记录器,到目前为止,我已经将日志消息打印到我的 JS 控制台(FF 的 Firebug): 最终,我希望非SEVERE 消息转到consoleHa
我是一名优秀的程序员,十分优秀!