从问题角度来思考设计模式(2) – 结构编
来源:互联网 发布:js复制一个对象 编辑:程序博客网 时间:2024/05/17 01:19
目录
- 生成编
让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); } @Override public void move(FooPosition position) { position.setX(position.getX() + addition); }}public class FooMoveVertical extends FooMove { public FooMoveVertical(int addition) { super(addition); } @Override public 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); } @Override public 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); } @Override public 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 { @Override public void foo1() { // NormalUser foo1 } @Override public void foo2() { throw new RuntimeException("this operation is not permitted."); } @Override public void foo3() { throw new RuntimeException("this operation is not permitted."); }}public class FooNormalUser extends FooUser { @Override public void foo1() { // NormalUser foo1 } @Override public void foo2() { // NormalUser foo2 } @Override public void foo3() { throw new RuntimeException("this operation is not permitted."); }}public class FooSuperUser extends FooUser { @Override public void foo1() { // SuperUser foo1 } @Override public void foo2() { // SuperUser foo2 } @Override public 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(); @Override public void foo1() { normalUser.foo1(); } @Override public void foo2() { throw new RuntimeException("this operation is not permitted."); } @Override public void foo3() { throw new RuntimeException("this operation is not permitted."); }}NormalUser和SuperUser类保持不变
通过Proxy
模式,控制对某个对象的访问。如果需要,可以给不同的用户提供不同级别的使用权限。查看原文:http://www.huuinn.com/archives/301
更多技术干货:风匀坊
关注公众号:风匀坊
阅读全文
0 0
- 从问题角度来思考设计模式(2) – 结构编
- 从问题角度来思考设计模式(1)
- 从问题角度来思考设计模式(3)
- 从面相对象来思考设计模式
- 从哲学的角度来思考程序
- 从设计模式来说如何思考问题?
- 从研究的角度来思考软件设计模式——研究方向
- 培训-从学员的角度思考问题
- 设计模式------从小说的角度来理解
- 从实例角度分析Java设计模式
- 从设计模式角度看ArcGIS Engine
- 从spark源码的角度思考scala中的模式匹配
- 从追MM谈23种设计模式 --- 很经典! 学会用设计模式思考问题
- 换角度思考问题
- 思考问题的角度
- 从易于扩展扩展的角度来设计FizzBuzzWhizz
- 从AI的角度来分析斗地主设计
- 从模式角度理解Android架构设计-Facade模式
- bandit算法(1)--epsilon-Greedy Algorithm(附代码)
- [C语言]用C语言处理简单的计算题
- js---原生JS数组arr遍历方法forEach()和map()遍历的区别以及兼容写法
- C语言:分步编译一个C程序
- 日常积累--javaweb
- 从问题角度来思考设计模式(2) – 结构编
- git使用笔记
- 墙上的门
- 区块链Block创建时间
- Diophantus of Alexandria HDU
- 命名空间using的几种常用方法
- 17/10/12训练日记
- Linux基本命令3
- org POI核心类