设计模式无处不在,我们可以在各种开源框架中识别到各种设计模式是如何被巧妙地应用的。BlackStar,虽然并不刻意,但也使用到很多设计模式。我们来看看BlackStar的Reporter,看一些常用的设计模式是如何使其更加灵活和可扩展的。
1.什么是Reporter
BlackStar的JVM Monitor会进行JVM监控数据的采集,采集后的数据如何处理呢,就交个Reporter去进行数据的处理。
2.策略模式
数据处理可能记录到文件、也可能调用远端服务器接口进行记录、也可能存储到数据库,对于JVM Monitor来说,不会关心Reporter如何去存储数据,这就是策略模式。

如下上策略接口定义
public interface ResultReporter
{
void report(ReportData data);
}
3.装饰模式
为了不影响JVM Monitor继续后续的工作,对于结果记录我们希望采用异步的方式去处理,然而如果每种策略实现者都需要自己去处理异步,当然是一个很冗余乏味的工作,我们使用装饰模式来处理

下面是异步Reporter的实现(代码做了裁减)
public class AysnResultReporter implements ResultReporter
{
private final static Log LOGGER = LogFactory.getLog(AysnResultReporter.class);
private ResultReporter targetResultReporter;
private ExecutorService executorService;
public AysnResultReporter(ResultReporter targetResultReporter,
ExecutorService executorService)
{
super();
this.targetResultReporter = targetResultReporter;
this.executorService = executorService;
}
public void report(final ReportData data)
{
this.executorService.execute(new Runnable()
{
public void run()
{
targetResultReporter.report(data);
}
});
}
}
看下面的示例
ResultReporter reporter = new AsynResultReporter(new FileReporter(...), executorService);
//异步、文件Reporter
ResultReporter reporter = new AsynResultReporter(new HessianReporter(...), executorService);
//异步、Hessian Reporter
4.组合模式
我们的目标当然不仅仅这么简单,为了保证采集的数据一定会被记录,我们可能要求首先使用远程模式记录,而远程模式记录错误时,则使用文件记录,或者我们可能要求使用多个Reporter同时记录,我们看看组合模式如何处理的

看看ListResultReporter的实现
public class ListResultReporter implements ResultReporter
{
private final static Log LOGGER = LogFactory
.getLog(ListResultReporter.class);
private boolean isAndMode = true;
private List<ResultReporter> list = new ArrayList<ResultReporter>();
public ListResultReporter()
{
this(true);
}
public ListResultReporter(boolean isAndMode)
{
this.isAndMode = isAndMode;
}
public void addResultReporter(ResultReporter reporter)
{
this.list.add(reporter);
}
public void report(ReportData data)
{
for (ResultReporter reporter : list)
{
if (isAndMode)
{
reporter.report(data);
} else
{
try
{
reporter.report(data);
return;
} catch (Exception e)
{
LOGGER.error("Error When Report[" + reporter + "]", e);
}
}
}
}
}
看看怎么使用
ListResultReporter reporter = new ListResultReporter();
reporter.addResultReporter(new FileReporter(...));
reporter.addResultReporter(new HessianReporter(...));
5.适配器模式
我们知道,对于数据库的写入,一次批量写总是要比多次写要高效地多,因此对于数据库的Reporter,会使用一个BatchResultReporter的接口,而Monitor使用的是ResultReporter接口,因此需要在它们之间做一个适配

BatchResultReporter接口
public interface BatchResultReporter
{
void reportBatch(List<ReportData> datas);
}
适配器
public class BatchReporterAdapter implements ResultReporter
{
private final static Log LOGGER = LogFactory
.getLog(BatchReporterAdapter.class);
private final Object LOCK = new Object();
private BatchResultReporter targetBatchResultReporter;
private long maxBatchSize = 1000L;
private List<ReportData> datas = new ArrayList<ReportData>();
public BatchReporterAdapter(BatchResultReporter batchResultReporter)
{
super();
this.targetBatchResultReporter = batchResultReporter;
}
public void setMaxBatchSize(long maxBatchSize)
{
this.maxBatchSize = maxBatchSize;
}
public void report(ReportData data)
{
List<ReportData> oldDatas = null;
synchronized (LOCK)
{
this.datas.add(data);
if (this.datas.size() >= this.maxBatchSize)
{
oldDatas = this.datas;
this.datas = new ArrayList<ReportData>();
}
}
if (oldDatas != null)
{
commit(oldDatas);
}
}
public void commit()
{
List<ReportData> oldDatas = null;
synchronized (LOCK)
{
oldDatas = this.datas;
this.datas = new ArrayList<ReportData>();
}
commit(oldDatas);
}
protected void commit(List<ReportData> datas)
{
LOGGER.info("commit batch report data[" + datas.size() + "]");
try
{
this.targetBatchResultReporter.reportBatch(datas);
} catch (Exception e)
{
LOGGER.error("Error When commit batch datas", e);
}
LOGGER.info("commit success");
}
}
6.工厂模式
如何将上面这些各种各样的Reporter创建出来呢,我们可以选择使用简单xml配置的方式来管理这些Reporter并创建,我们也可以依赖于其他的创建工厂,譬如Spring,这就是工厂模式

工厂接口如下
public interface ReporterFactory
{
ResultReporter createReporter(String name);
}
分享到:
相关推荐
微信小程序电商项目是一种基于微信平台的应用...此外,参与项目还可以学习到电商应用的常见设计模式和最佳实践,对个人技能的提升大有裨益。记得在GitHub上给予项目“star”支持,以便更多的人受益于这样的学习资源。
- **Blackstar Amplification**:专注于创新技术的应用,为吉他手提供独特的声音体验。 - **Hughes & Kettner**:德国品牌,以其高品质的手工制作吉他放大器而知名。 - **Orange Music Electronic Company**:英国...
:glowing_star: 响应式网页设计 截屏 :camera_with_flash: 工具 :desktop_computer: :paintbrush: :black_nib: :crayon: 作者 :woman::laptop: 保持联系 :purple_heart: 可用脚本 在项目目录中,可以运行: ...
得实DS-1000是一款由得实发展集团与日本西铁城联合研发的小型平推式打印机,其设计紧凑,适用于空间有限的工作环境。该打印机支持5英寸(127毫米)的打印宽度,具备前后双方向平推式进纸功能,能够实现高速打印,...
:black_large_square: 暗模式版本 :white_large_square: 灯光模式版本 :writing_hand: 入门 :fast_down_button: 安装: git clone https://github.com/kaguwomin/modern-next-portfolio # after cloning ...
全新酷炫的黑暗模式 :black_heart: 渐变填充到波浪 :rainbow: 快来了... 应用程序 :star: 贡献和Hacktoberfest :red_heart: 我们衷心欢迎您为解决问题,添加新的自定义项或只是改进样式而做出的新贡献。 我们真正地 ...
- **滚动队列与前向星表示法 (Rolling Queue and Forward Star Representation)** - 定义:用于高效维护队列和图的表示。 - **最小点基与最小权点基 (Minimum Point Basis and Minimum Weight Point Basis)** - ...
如何开始使用如果你喜欢SuperTextView,希望能顺手在Github点个star哦!抽出空余时间写文章分享需要动力,还请各位看官动动小手点个赞,给我点鼓励我一直在不定期的创作新的干货,想要上车只需进到我的【个人主页】...
6. **技术与社会影响**:语言机器的普及将对社会产生深远影响,可能改变通信方式、文化交流、工作市场甚至人类的认知模式。例如,自动翻译可以消除语言障碍,但同时也可能引发就业问题和隐私问题。 7. **版权与许可...