从问题角度来思考设计模式(2) – 结构编
目录
- 生成编
让API返回信息适配多样性
- 改造前
FooAPI fooAPI = new FooAPI(lat, lng);
FooPlace place = new FooPlace();
place.setAddress(fooAPI.getPostalCode() + " " + fooAPI.getAddress()); // 邮编 **市**区
place.setStation(new StringJoiner(",").add(fooAPI.getStation1()).add(fooAPI.getStation2()).add(fooAPI.getStation3()).toString()); //A车站,B车站,C车站
上面代码是API返回信息整形用例。这里只使用了FooAPI
,未来如果返回信息的整形方式不变的话,倒也没有什么问题。但从易维护的角度思考,这称不上一个好的设计。
- 改造后 Adapter
public class FooAPIAdapter {private final FooAPI fooAPI;public FooAPIAdapter(double latitude, double longitude) {this.fooAPI = new FooAPI(latitude, longitude);}public String getAddress() {return fooAPI.getPostalCode() + " " + fooAPI.getAddress();}public String getStation() {return new StringJoiner(",").add(fooAPI.getStation1()).add(fooAPI.getStation2()).add(fooAPI.getStation3()).toString();}
}
FooAPIAdapter fooAPI = new FooAPIAdapter(lat, lng);
FooPlace place = new FooPlace();
place.setAddress(fooAPI.getAddress());
place.setStation(fooAPI.getStation());
在这里引入了Adapter(适配器)
的概念。当返回信息的整形方式改变的时候,只要修改对应的Adapter
类就可以,而对调用方不会产生代码改动。引入设计模式的初衷都为了,业务上的解耦,让代码更聚焦。
让API调用方不需要考虑操作顺序
- 改造前
public class FooSorter {private List<FooStudent> students = new List<>();public void add(FooStudent student) {students.add(student);}public void sort() {students.sort(Comparator.comparingInt(student -> student.getChineseScore()+ student.getMathScore()+ student.getEnglishScore()).reversed());}public List<FooStudent> getResult() {return students;}
}
FooSorter sorter = new FooSorter();
sorter.add(student1);
sorter.add(student2);
sorter.add(student3);
sorter.sort();
sorter.getResult();
需要遵循实例生成 -> add() -> sort() -> getResult()
流程来调用,调用方如果不知道流程则调用失败,故这样的设计并不好。
- 改造后 Facade
public class FooSorter {private List<FooStudent> students = new List<>();private FooSorter() {}public static List<FooStudent> sort(FooStudent... students) {for (FooStudent student : students)add(student);sort();return getResult();}private void add(FooStudent student) {students.add(student);}private void sort() {students.sort(Comparator.comparingInt(student -> student.getChineseScore()+ student.getMathScore()+ student.getEnglishScore()).reversed());}private List<FooStudent> getResult() {return students;}
}
FooSorter.sort(student1, student2, student3);
调用方不需要知道排序逻辑,且调用代码行数也缩减1行。涉及多个类按顺序执行复杂的处理时,可以考虑使用Facade
模式。常见的有,手机的一键静音模式,该模式包括了音量设置,振动器设置等。玩魔兽世界的玩家肯定更熟悉,就是传说中的一键宏,惩戒骑用脸滚键盘的回忆有木有。
让同级类的结果组合起来
- 改造前
public class FooPosition {private int x;private int y;public void moveAs(FooMove move) {move.move(this);}
}public abstract class FooMove {private final int addition;public FooMove(int addition) {this.addition = addition;}public abstract void move(FooPosition position);
}public class FooMoveHorizontal extends FooMove {public FooMoveHorizontal(int addition) {super(addition);}@Overridepublic void move(FooPosition position) {position.setX(position.getX() + addition);}
}public class FooMoveVertical extends FooMove {public FooMoveVertical(int addition) {super(addition);}@Overridepublic void move(FooPosition position) {position.setY(position.getY() + addition);}
}
FooMove moveHorizontal = new FooMoveHorizontal(x);
FooMove moveVertical = new FooMoveVertical(y);FooPosition position = new FooPosition();
position.moveAs(moveHorizontal);
position.moveAs(moveVertical);
上面的代码本身设计没有什么问题,但每次都只能往一个方向,要么水平要么垂直方向移动。如何实现一次调用能达到同时操作x,y呢?
- 改造后 Decorator
public class FooPosition {private int x;private int y;public void moveAs(FooMove move) {move.move(this);}
}public abstract class FooMove {private final int addition;private final FooMove move;public FooMove(int addition) {this.addition = addition;}public FooMove(int addition, FooMove move) {this.addition = addition;this.move = move;}public abstract void move(FooPosition position);
}public class FooMoveHorizontal extends FooMove {public FooMoveHorizontal(int addition) {super(addition);}public FooMoveHorizontal(int addition, FooMove move) {super(addition, move);}@Overridepublic void move(FooPosition position) {if (move != null)move.move(position);position.setX(position.getX() + addition);}
}public class FooMoveVertical extends FooMove {public FooMoveVertical(int addition) {super(addition);}public FooMoveVertical(int addition, FooMove move) {super(addition, move);}@Overridepublic void move(FooPosition position) {if (move != null)move.move(position);position.setY(position.getY() + addition);}
}
FooMove move = new FooMoveHorizontal(x, new FooMoveVertical(y));FooPosition position = new FooPosition();
position.moveAs(move);
x,y移动的距离汇总到move
这个实例中。且利用这个设计,当移动结束时,还想再水平移动时只需要简单的new FooMoveHorizontal(x, move)
就可以。 有兴趣的朋友可以思考下左左右右上上下下
如何用类来生成?
根据条件不同控制权限
- 改造前
public class FooTestUser extends FooUser {@Overridepublic void foo1() {// NormalUser foo1}@Overridepublic void foo2() {throw new RuntimeException("this operation is not permitted.");}@Overridepublic void foo3() {throw new RuntimeException("this operation is not permitted.");}
}public class FooNormalUser extends FooUser {@Overridepublic void foo1() {// NormalUser foo1}@Overridepublic void foo2() {// NormalUser foo2}@Overridepublic void foo3() {throw new RuntimeException("this operation is not permitted.");}
}public class FooSuperUser extends FooUser {@Overridepublic void foo1() {// SuperUser foo1}@Overridepublic void foo2() {// SuperUser foo2}@Overridepublic void foo3() {// foo3}
}
TestUser
只能执行NormalUser
类中的foo1
方法,执行foo2
或foo3
方法时会报错。 从上面的代码可以发现TestUser
和NormalUser
的foo1
代码内容是一样,返回了dry(Don't repeat yourself)原则。
- 改造后 Proxy
public class FooTestUser extends FooUser {private FooUser normalUser = new FooNormalUser();@Overridepublic void foo1() {normalUser.foo1();}@Overridepublic void foo2() {throw new RuntimeException("this operation is not permitted.");}@Overridepublic void foo3() {throw new RuntimeException("this operation is not permitted.");}
}NormalUser和SuperUser类保持不变
通过Proxy
模式,控制对某个对象的访问。如果需要,可以给不同的用户提供不同级别的使用权限。
查看原文:http://www.huuinn.com/archives/301更多技术干货:风匀坊关注公众号:风匀坊
从问题角度来思考设计模式(2) – 结构编相关推荐
- 什么是经验--从程序员角度的思考
为啥会思考这个问题? 刚才在骑车回家的路上,脑子里突然闪过纪录片里关于爱因斯坦研究出相对论和他的大脑的关系.我就在想,他当时在思考时间和空间时,是不是因为他脑袋里面其实存在一个关于时间和空间的模块,只 ...
- 为什么要使用低代码 – 前端角度的思考
为什么要使用低代码 – 前端角度的思考 文章目录 为什么要使用低代码 – 前端角度的思考 当前前端发展现状 低代码的热潮已经掀起千层浪 UI工程师常常面临一些令人尴尬的场景 低代码化解场景思路 低代码 ...
- 校园导游图C语言数据结构,用C语言和数据结构中的无向图存储结构编一个校园导游图完全的程序代码.docx...
用C语言和数据结构中的无向图存储结构编一个校园导游图完全的程序代码.docx 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下 ...
- 一个完整的c语言程序结构图,用C语言和数据结构中的无向图存储结构编一个校园导游图完全的程序代码.docx...
用C语言和数据结构中的无向图存储结构编一个校园导游图完全的程序代码 #define Infinity 1000 #define MaxVertexNum 35 #define MAX 40 #incl ...
- C++求复数的角度_【研读.教材分析】“勾股定理”教学——基于单元整体的角度再思考...
(西安市第八十六中学 刘丽丽) 学科教学要注重知识的"生长点"和"延伸点",把课时知识置于学科整体逻辑体系中,关注结构和通法,处理好局部与整体之间的关系.所 ...
- 用户体验已成过去时 AI要从公民乃至社会的角度去思考问题
来源:Venture Beat 作者:Jarno M. Koponen 编译:科技行者 时至今日,科技巨头及其基于AI的数字平台与解决方案,完全有能力影响全球领导人.民族国家.跨国企业.全球股市乃至每 ...
- 技术思考--不要从技术的角度去思考大数据的落地
在明确了自己在大数据方向里的具体模块后,就只剩下来加强自己这一方面的突破跟技术积累了.我选择是数据分析及可视化两个方向.行业是传统行业,为什么是这样?下面就从业务角度来层层分析. 一直以来,都觉得太过 ...
- java和设计模式(结构模式)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 在设计模式中,有一类设计模式是比较有意思的,但是关注的人不多.这就是结构模式.如果说创建模式的重 ...
- 从动态的角度分析DDR的时序结构
从整体上了解了DDR的特性和静态图,包括原理.管脚图等.那么本章就要从动态的角度来分析时序结构,包括read/write的整个过程到数据返回发生了什么. 一,DRAM基本组成 对于DRAM,其主要由行 ...
最新文章
- [转+个人整理]从D触发器的逻辑结构说明建立时间和保持时间
- 字符串拼接+和concat的区别
- 【英语学习】【加州教材】【G2】【科学】Science目录及术语表
- 【ElasticSearch】 ElasticSearch 写入流程
- 设计资源 | 万圣节矢量图标
- 【转载】UltraWinGrid使用心得(C#)
- 用Java获取当前工作目录
- jfinal 一对一 实体类怎么写_新祥旭考研一对一:考前必知的四大答题技巧
- Unity C#笔记 委托事件
- Arbor Networks Spectrum新安全平台发布:高级威胁平台通过内部企业网络连接互联网上的攻击...
- 读书笔记之深入理解Java虚拟机
- MessageDigest详解
- 微信小程序开发——上传图片
- 天津等保测评机构项目测评收费价格标准参考
- 2020软科中国计算机学科排名,【智库数据】基于2020软科中国最好学科排名的学科动态发展跟踪...
- 微信小程序多次跳转后不能点_微信突然更新,但我劝你这次别升级
- 前端解决图片404的问题
- 集成科大讯飞语音合成
- 30年前他发明了万维网,现在他要颠覆互联网
- buuctf crypto 萌哒哒的八戒
热门文章
- 计算机网络域搭建,计算机网络课程设计_组建局域网及搭建服务器(26页)-原创力文档...
- java 数组类型定义_java定义数组的三种类型总结
- oracle卸载的步骤,Oracle卸载步骤(Windows)
- 宏基Acer台式机 win8 改win7 按F12没有U盘启动选项
- paddle+qt部署方案
- miui12怎么自定义开机动画_小米6最新版MIUI12体验
- VS好用系列之代码片段
- {{小仓鼠爱攒食物}}Node
- 夜幕,又一次降临。窗外,风呼呼的刮着
- 如何在pe里加载阵列卡驱动_如何用PE为Server08手动加入阵列卡驱动