优雅のJava(七)—— 优雅的适配 优雅的外观 适配器模式 外观模式

优雅のJava(七)—— 优雅的适配 优雅的外观 适配器模式 外观模式,第1张

优雅のJava(七)—— 优雅的适配 优雅的外观 适配器模式 外观模式

文章目录

前言适配器模式——转接头 接口之间的翻译

单向转接双向转接 外观模式——套层皮

迪米特原则 最少知识原则 后记

前言

这篇会同时聊到了前边介绍过的代理模式(应该说特指静态代理) 装饰器模式 还有本篇需要讲的 外观模式(Facade)和适配器(Adapter)模式

原因是 技术上他们真的非常类似—— 就是引用别人组件的实例对象 到自己的方法里边 然后调用别人的 完成自己的目的

我前边说过 关键不在于技术 而在于思想 这里我们就从这种让人迷惑的 很接近的技术实现方式出发 理解这几种种模式的相关性

适配器模式——转接头 接口之间的翻译 单向转接

其实单向转接头 实现起来我认为和代理一个道理的 只不过 代理追求的是 和被代理对象一个接口规范 而转接 就是用新接口取代旧接口就完事了嘛。。。

比方说 原来老的接口是2D4GHz 现在是2.4G+5G(5GHz)都能通用的 但是老的设备 比如我的老手机 它不支持这个新接口5Ghz 该怎么办?

	public interface 2D4G {
		// 以前没想过还会有别的频段的信号 默认是2.4GHz 所以这里直接emitSignal
		public void emitSignal();
	}
	public class Mao implements 2D4G{
		public void emitSignal() {
			System.println.out("2D4G sig emited");
		}
	}
	public class MyOldPhone {
		public void UsingInternet(2D4G mao){
			mao.emitSignal();
		}
	}
	public class Me {
		public static void main(String[] args) {
			MyOldPhone myphone = new MyOldPhone();
			myphone.UsingInternet(new Mao());
		}
	}

结果现在不提供旧的网络了 Mao也换成光猫了:

	public interface 5G {
		public void emit5Gsignal();
		public void emitBothSignal();
		public void emit2D4GSignal();
	}
	public class OpticalMao implements 5G {
		public void emit5Gsignal() {
			System.println.out("5G sig emited");
		}
		public void emit2D4Gsignal() {
			System.println.out("2.4G sig emited");
		}
		public void emitBothsignal() {
			System.println.out("Both 2.4G and 5G sig emited");
		}
	}

你会发现 我这光猫放进去他不行啊 他不是2D4G的规范 :

	public class Me {
		public static void main(String[] args) {
			MyOldPhone myphone = new MyOldPhone();
			myphone.UsingInternet(new OpticalMao());
		}
	}

这时 我们需要一个 光猫转普通猫 或者说应该是5G标准的实例 单向转到2.4G的实例

	public class MaoAdapter implements 2D4G{
		private 5G opticalMao = null;
		public MaoAdapter(5G opticalMao)(
			this.opticalMao = opticalMao;
		}
		public void emitSignal(){
			this.opticalMao.emit2D4Gsignal();
		}
	}

然后 我 就能这么用我的手机了:

	public class Me {
		public static void main(String[] args) {
			MyOldPhone myphone = new MyOldPhone();
			myphone.UsingInternet(new MaoAdapter(new OpticalMao()));
		}
	}

其实就是一个外壳 说白了 一个为实例 做单向转接口规范的事情 或者说 就是个简单的翻译

双向转接

这个就稍微有点意思起来了 原来是 只是换了层皮 现在要做两面人 两边都要通
比方说我们举个例子 有个哥们 有支持5Ghz Wifi 接口的手机 但是悲惨的是 家里的Mao很老 只支持2.4G接口的信号 另外一个老哥 有光猫有5G 但是 只有个老手机 支持2.4G而已(没错 就是我哒)

这时我们需要一个双向接口!

我们来看看有了双向接口 理想的效果:

	// 5G光猫 - 2.4G手机
	public class 2D4GPhone {
		public void UsingInternet(2D4G mao){
			mao.emitSignal();
		}
	}
	public class Me {
		public static void main(String[] args) {
			MyOldPhone myphone = new 2D4GPhone();
			myphone.UsingInternet( new TwoWayAdapter(new OpticalMao()) );
		}
	}
	// 2.4G猫 - 5G手机
	public class 5GPhone {
		public void UsingInternet(5G opticalMao){
			opticalMao.emit2D4GSignal();
		}
	}
	public class Me {
		public static void main(String[] args) {
			MyOldPhone myphone = new 5GPhone();
			myphone.UsingInternet( new TwoWayAdapter(new Mao()) );
		}
	}

那么 这个双向接口应当如何设计? 其实还是翻译 只不过我们两种接口规范都需要支持才对!

	public class TwoWayAdapter implements 5G, 2D4G{
		private 5G opticalMao = null;
		private 2D4G mao = null;
		public TwoWayAdapter(5G opticalMao)(
			this.opticalMao = opticalMao;
		}
		public TwoWayAdapter(2D4G mao)(
			this.mao = mao;
		}
		
		// 2.4G手机会调用的
		public void emitSignal(){
			this.opticalMao.emit2D4Gsignal();
		}
		
		// 5G手机会调用的
		public void emit2D4GSignal(){
			this.mao.emitSignal();
		}
		
		// 真需要5G信号的部分 那没办法 只能搞个光猫了 或者骗骗自己:)至少能用吧
		public void emit5Gsignal(){
			this.mao.emitSignal();
		}
		public void emitBothSignal(){
			this.mao.emitSignal();
		}
	}

可以发现 就是 有2.4G的实例 我调用它 完成既定接口需要的功能 然后套层壳当5G的实例使用:)

可以参考 鸭式辩型

像鸭子一样走路、游泳并且嘎嘎叫的鸟就是鸭子

因为鸭子这个接口规范的要求都满足 那就可以使用 客户不需要知道底层的细节

外观模式——套层皮

还记得之前的静态代理吗 我们就是引用别的组件 执行以下 执行的前后可能做些记录之类的 这是为了代理那个组件

同样的道理 如果代理一顿 *** 作呢?比如需要好几个组件顺序执行 你同样可以引用 流程需要的所有组件 每个执行一遍即可 比如坐飞机=值机+安检+登记+降落+出站 说白了就是封装一层 *** 作 没啥大不了的

这里可以举个简单的例子 比如你是老板 想做个网站 但是你也不懂技术 咋办?自然是使唤人来做啊 而且老板往往不会直接和下边员工布置具体的任务 ——他也不会啊 但是 他手下有主管经理 所以

老板所知的 只是经理能够安排好人手 搞定这个网站 而不是去管那些底层细节!

相当于 底层对老板而言不可见 也没必要见 老板只需要找到经理 这个经理就相当于封装了一层外观Facade

	public class Boss(){
		private Manager manager = null;
		public Boss(Manager manager){
			this.manager = manager;
		}
		private void IWantAWebsite(){
			this.manager.executeWebsitePlan();
		}
	}	
	
	public class Manager(){
		// ...
		public void executeWebsitePlan(){
			frontEndDeveloper().developing();
			userEndDesigner().designing();
			backEndDeveloper().developing();
			OperationsEngineer().operating();
		}
	}

	public class company(){
		public static void main(String[] args){
			Boss boss = new Boss(new Manager());
			boss.IWantAWebsite();
		}
	}

可以发现 老板执行一句话 下边千军万马:)

迪米特原则 最少知识原则

看过专栏 有篇讲七大原则的兄弟可能还记得这个迪米特原则 说白了 老调重d——客户不想 也没必要知道底层 你怎么代理 转换 外观 I dont care(idk) 反正你符合交货接口规范就行

迪米特原则强调 类与类直接 应当尽量减少耦合 换言之 只需要最小的知识即可 互相了解的越少越好 最好是没任何耦合:)

只和你的朋友说话 不要和陌生人讲

这样 耦合度 耦合的范围可以降到很低 出问题 定位容易 改错成本低

牵一发动全身的那种 往往就是 “知道的太多了” 依赖别的类 需要知道的东西太多了 耦合代码也太多了 GG

后记

还是那句话 重要的是思想 而不是技术实现

适配器重点是接口规范 乃至父类规范的适配(这个对于多继承语言有用 java只能说接口规范了)

外观的重点是屏蔽底层

代理的重点是 同规范 同功能 我给您代理

装饰器的重点是装饰 增添新特性

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5703366.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存