【0】README
0.1)本文部分文字描述转自 “head first设计模式”,旨在学习 外观模式 的基础知识;
0.2)突然有个发现:在我的荔枝中,我将外观模式用于 简化了处理 cluster的预备工作的接口,而我用模板方法模式应用于封装具体的 kmeans聚类算法;(干货——也即我将外观模式和模板方法模式结合到了 kmeans聚类算法的实现中),如何将模板方法模式应用到kmeans中,参见 模板方法模式应用到kmeans
【1】外观模式
1)外观模式定义: 提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用;
2)引入最少知识原则:该原则告诉我们要减少对象之间的交互,只留下几个密友;
3)problem+solution:
3.1)problem:如何不要赢得太多的朋友和影响太多的对象的处理方法?
3.2)solution:最少知识原则提供了一些方针: 就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:
- method1)该对象本身;
- method2)被当做方法的参数而传递进来的对象;
- method3)此方法所创建或实例化的任何对象;
- method4)对象的任何组件;
Attention)
- A1)method1+2+3 告诉我们:如果某对象是调用其他方法的返回结果,不要调用该对象的方法;
- A2)method4:把组件想象成是被实例变量所引用的任何对象,换句话说,把这想象成是“有一个”(has-a)的关系;
【2】外观模式的应用背景
2.1)problem:跑kmeans算法(最困难的方式),想要跑聚类算法,需要事先执行一些任务:收集数据;数据清洗;接着将数据写入到xlsx(以方便作图);然后将数据读入到内存(数组);这些执行完之后,才能跑聚类算法,不觉跑个聚类算法这么麻烦,而且跑完之后,我还需要统计聚类结果(将聚类结果持久化到 磁盘的xlsx文件);
2.2)solution:需要一个外观模式,有了外观模式,通过实现一个提供更合理的接口的外观类,你可以将一个复杂的子系统变得容易使用。如果你需要复制子系统的强大威力,别担心,还是可以使用原来的复杂接口的;但如果你需要的是一个方便使用的接口,那就使用外观;
Complementary)
- C1)外观不只是简化了接口,也将客户从组件的子系统中解耦;
- C2)外观和适配器可以包装许多类,但是外观的意图是简化接口,而适配器的意图是将接口转换为不同接口;
Conclusion)
- C1)一句话,使用外观模式,把 跑 kmeans算法 事先需要执行的任务封装起来,之后,仅仅只需要调用 kmeans()这个方法就可以了, 你会发现跑个算法是这样简单,哈哈;
- C2)适配器模式+装饰者模式+外观模式的总结:适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的 行为和责任;而外观将一群对象包装起来以简化其接口;
【3】上干货荔枝代码(以跑kmeans聚类算法为例)
- step1)先给出外观模式
public class KmeansFacade { DataCollector collector; // 数据收集器 DataCleaner cleaner; // 数据清洗器 DataTransformToXlsx transformer; //数据转换器 DataReader reader; // 数据读入内存 DataWriter writer; // 数据持久化到磁盘 // 以上都是子系统 的类 public KmeansFacade() { this.collector = new DataCollector(); this.cleaner = new DataCleaner(); this.transformer = new DataTransformToXlsx(); this.reader = new DataReader(); this.writer = new DataWriter(); } public KmeansFacade(DataCollector collector, DataCleaner cleaner, DataTransformToXlsx transformer, DataReader reader, DataWriter writer) { this.collector = collector; this.cleaner = cleaner; this.transformer = transformer; this.reader = reader; this.writer = writer; } // 实现简化的接口 public void cluster() { collector.collect(); cleaner.clean(); transformer.transformToXlsx(); reader.readToArray(); System.out.println("this is kmeans cluster alg"); } // 实现简化的接口 public void end_cluster() { writer.writeToDisk();//聚类完成后,写入聚类结果到磁盘 // 或许聚类后,你还需要干其他事情,都可以在这里添加...... } }
- step2)子系统的各个组件(数据收集器+数据清洗器+数据转换器+数据读入内存+数据持久化到磁盘)
public class DataCollector { public void collect() { System.out.println("collect data"); } }
public class DataCleaner { public void clean() { System.out.println("clean data"); } }
public class DataTransformToXlsx { public void transformToXlsx() { System.out.println("transform data from text to xlsx"); } }
public class DataReader { public void readToArray() { System.out.println("read data to array"); } }
运行结果)public class DataWriter { public void writeToDisk() { System.out.println("after kmeans, write data from array to xlsx"); } }
collect data clean data transform data from text to xlsx read data to array this is kmeans cluster alg after kmeans, write data from array to xlsx