苹果手机怎么用推特代理加速器(苹果手机怎么使用推特app)
苹果应用商店背后的设计模式;一个被Eclipse,NetBean等项目使用的设计模式;一个化“多对多”为“一对多”的设计模式;一个码农老吴不得不使用GUI项目的设计模式;一个技可进乎道的设计模式;一个格局太大,反而籍籍无名的设计模式;一个码农习以为常而不自知的设计模式。
谁在说我?
大家好,极客架构师——专注架构师成长,我是码农老吴。
本期是《架构师基本功之设计模式》弟17期。
在弟16期,我给大家分享了,行为型设计模式中的观察者设计模式,
我认为它是一个命运多舛,坚韧不拔的设计模式,它的发展历程源远流长:
C/S时代:发迹于GUI项目,
B/S时代:隐身于MVC模式,
RPC时代:大器晚成,修成正果,成为了消息系统的灵魂。
在本期,我们要分享的设计模式,从马斯克反对苹果“应用商店”高额“苹果税”说起。
马斯克反对苹果“应用商店”高额“苹果税”
这一段时间,马斯克频频上头条,先是大批裁员引起热议,接着吐槽Twitter的“RPC”技术,被码农回怼,脸上挂不住,Twitter上直接开除了回怼他的员工,现在,又和苹果干起来了,颇有见神杀神,见佛杀佛的架势。
大佬,就是大佬,路见不平一声吼,公开反对苹果的应用商店“30%”,高额的“苹果税”,并且扬言,如果苹果敢把Twitter在苹果的“应用商店”下架,就自己造手机。苹果的库克估计是怕了,连夜赶紧邀请马斯克参观苹果总部,并表示苹果无意把推特从“应用商店”下架,马斯克的影响力可见一斑。
你敢下架Twitter吗?
我的故事就从苹果的“应用商店”说起,大家还记得早些年,还没有苹果“应用商店”或者其他软件应用商城,电脑是如何安装软件的吗?我自己经历过三个时代:
光盘时代
那个时候我住在北京中关村附近的城中村,一到周末,就骑着自行车,要么到中关村的书店看书,要么到海龙大厦,太平洋大厦,或者硅谷电脑城,那个时候,走在中关村的路上,常常能遇到传说中抱着孩子卖光盘的大姐,我那个时候挺纳闷,为啥买光盘要抱个孩子,到现在我还没想明白。
官网下载时代
那个时候,笔记本还不太流行,我使用的电脑,常常是自己在中关村买配件,攒的电脑,蕞幸福的时刻,就是安装完所有配件,开机开始安装各种软件和驱动程序的时刻,下载电脑驱动程序,就到软件的官网,一个一个的下载。
应用商店或者软件下载网站时代
比如华军软件园,中关村下载,驱动之家什么的,下载软件就方便多了。
后来,自从使用了苹果笔记本,下载软件,在苹果的appStore,点击一下就可以了,方便多了,驱动程序是什么都快忘了。
下载网站和应用商店,背后的商业逻辑,就符合我们今天要分享的设计模式——中介者模式。
结论先行
基于REIS分析模型,中介者模式由两个角色组成,分别是中介者角色,同事角色,它的宗旨是,通过中介者角色,将同事角色之间“多对多”的依赖关系,变成同事与中介之间的“一对多”关系,实现同事角色之间关系的解耦合。
开播预告
后面我分享的相关视频,一般会首先在直播中分享,希望大家多多捧场。
固定直播时间:每周六,晚上9点开播。
首播日期:12月10号
分享思路
技可进乎道
案例介绍:自定义combobox组件
弟一版代码:无设计模式
弟二版代码:基于中介者模式
中介者模式定义解析
REIS分析模型解析中介者模式
通用代码和类图
下期预告
技可进乎道
中介者模式之“中介”一词,普罗大众都很熟悉,租房找房屋中介,如我爱我家,链家等,找工作找职业中介,如Boss直聘,51Job啥的,相亲找婚姻中介,等等吧,我就不一一列出。
总而言之,中介在现实生活中太普遍了。而中介者模式则是对中介思想的抽象,按照一般的道理,中介者模式,在我们的软件中应该广泛使用才对,但是,如果你想在各种开源软件中,找中介者模式的使用案例,却寥寥无几,这是为何?
原因是就是中介的这种思想太普遍,“技可进乎道”,而道则无形。
执大象,天下往;往而不害,安平太。乐与饵,过客止。道之出口,淡乎其无味,视之不足见,听之不足闻,用之不足既。
老子《道德经》三十五章
就是因为中介者近乎一种思想,导致在项目里面,虽然使用它的地方很多,但是常常隐身于其他设计模式之后,比如外观模式,代理模式,观察者模式等等,都有中介的思想在里面。
中介者模式,在GOF原著里面,举的案例是GUI项目的案例,在分享设计模式的时候,我一直回避使用GUI项目,原因是,对于Java程序员,在实际开发中,很少有GUI项目。我在调查中介者模式在开源软件中的使用情况时,发现在Eclipse,NetBean等开源软件中,都使用了中介者模式,看来这次实在是躲不过去,不过开发Eclipse或者Idea插件,还是要懂一些Java的Swing开发,所以这次,我索性就做一个GUI项目。
案例介绍:自定义combobox组件
combobox组件,大家应该不会陌生,用户既可以在文本框中输入文字,又可以在列表框中选择现有的项目。上面的文本框组件,用于让用户输入内容,下面的列表框,则可以让用户选择一个选项。当用户在文本框中输入文字时,会对列表框的内容进行筛选,当用户选择了一个选项时,也会自动填充到文本框,所以两个组件是互动的。外来案例更能完整一些,我们再增加了状态栏组件,显式用户的操作。
现在我们就使用Java的swing组件,自定义一个combobox组件。
老规矩,我们先开发无设计模式版本的。
弟一版代码:无设计模式类图
提示,对于这个设计模式,大家重点关注类之间的依赖关系。
接口及类:
CompLib.java:组件库主程序
ListComp.java:自定义列表框组件
StateBarComp.java:自定义状态栏组件
TextFieldComp.java:自定义文本框组件
CompLib.java:组件库主程序
package com.geekarchitect.patterns.mediator.demo02;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.swing.*;import java.awt.*;import java.util.Arrays;public class CompLib { private static final Logger LOG = LoggerFactory.getLogger; public void init { JFrame CompLibFrame = new JFrame; CompLibFrame.setSize; CompLibFrame.setDefaultCloseOperation; JPanel comboboxPanel = createComboboxPanel; CompLibFrame.add; CompLibFrame.setVisible; } private static JPanel createComboboxPanel { JPanel comboboxPanel = new JPanel; comboboxPanel.setLayout); StateBarComp stateBarComp = new StateBarComp; TextFieldComp textFieldComp = new TextFieldComp; DefaultListModel<String> listModel = new DefaultListModel<>; listModel.addAll); ListComp listComp = new ListComp; textFieldComp.setListComp; textFieldComp.setStateBarComp; listComp.setTextFieldComp; listComp.setStateBarComp; comboboxPanel.add; comboboxPanel.add; comboboxPanel.add; return comboboxPanel; } public static void main { CompLib compLib = new CompLib; compLib.init; }}
ListComp.java:自定义列表框组件
package com.geekarchitect.patterns.mediator.demo02;import lombok.Data;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.swing.*;import javax.swing.event.ListSelectionEvent;import javax.swing.event.ListSelectionListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;@Datapublic class ListComp extends JList<String> { private static final Logger LOG = LoggerFactory.getLogger; private TextFieldComp textFieldComp; private StateBarComp stateBarComp; private DefaultListModel<String> LIST_MODEL; public ListComp { super; this.LIST_MODEL = LIST_MODEL; setModel; this.setLayoutOrientation; this.setSelectionMode; this.initListener; } public void initListener { this.addFocusListener; this.addListSelectionListener; } private void addListSelectionListener { this.addListSelectionListener { @Override public void valueChanged { String selectedValue = ListComp.this.getSelectedValue; if ) { LOG.info; stateBarComp.setText; textFieldComp.setText; } } }); } private void addFocusListener { this.addFocusListener { @Override public void focusGained { stateBarComp.setText; } @Override public void focusLost { } }); }}
StateBarComp.java:自定义状态栏组件
package com.geekarchitect.patterns.mediator.demo02;import javax.swing.*;public class StateBarComp extends JLabel { public StateBarComp { super.setText; }}
TextFieldComp.java:自定义文本框组件
package com.geekarchitect.patterns.mediator.demo02;import lombok.Data;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.swing.*;import javax.swing.event.DocumentEvent;import javax.swing.event.DocumentListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;@Datapublic class TextFieldComp extends JTextField { private static final Logger LOG = LoggerFactory.getLogger; private ListComp listComp; private StateBarComp stateBarComp; public static final String TIP = "请输入..."; public TextFieldComp { super; this.initListener; } public void initListener { addFocusListener; addDocumentListener; } private void addDocumentListener { this.getDocument.addDocumentListener { @Override public void insertUpdate { stateBarComp.setText; TextFieldComp.this.filterList; } @Override public void removeUpdate { stateBarComp.setText; TextFieldComp.this.filterList; } @Override public void changedUpdate { stateBarComp.setText; TextFieldComp.this.filterList; } }); } private void filterList { String currText = TextFieldComp.this.getText; LOG.info; SwingUtilities.invokeLater { @Override public void run { ListModel<String> listModel = listComp.getLIST_MODEL; DefaultListModel<String> filteredListModel = new DefaultListModel<>; if )) { filteredListModel = listModel; } else { for ; i++) { String item = listModel.getElementAt; if ) { filteredListModel.addElement; } } } listComp.setModel; listComp.repaint; } }); } private void addFocusListener { this.addFocusListener { @Override public void focusGained { stateBarComp.setText; if )) { TextFieldComp.this.setText; } } @Override public void focusLost { if )) { TextFieldComp.this.setText; } } }); }}
运行结果案例点评
这版代码,没有采用设计模式,每个组件各自为证,相互依赖,是典型的“多对多”依赖关系。
ListComp.java,自定义列表框组件,它依赖状态栏组件和文本框组件。
StateBarComp.java:自定义状态栏组件,它比较简单,不依赖别的组件,但是别的组件都依赖它。
TextFieldComp.java:自定义文本框组件,它依赖状态栏组件和列表框组件。
下版代码,我们采用中介者模式,对依赖关系进行简化。
弟二版代码:基于中介者模式类图接口及类
CompLibV2.java:组件库主程序
ComboboxCompMediator.java:中介者角色,实现类
ListCompColleague.java:同事角色,自定义列表框组件
StateBarCompColleague.java:同事角色,自定义状态栏组件
TextFieldCompColleague.java:同事角色,自定义文本框组件
CompLibV2.java:组件库主程序
package com.geekarchitect.patterns.mediator.demo03;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.swing.*;import java.awt.*;import java.util.Arrays;public class CompLibV2 { private static final Logger LOG = LoggerFactory.getLogger; public void init { JFrame CompLibFrame = new JFrame; CompLibFrame.setSize; CompLibFrame.setDefaultCloseOperation; JPanel comboboxPanel = createComboboxPanel; CompLibFrame.add; CompLibFrame.setVisible; } private static JPanel createComboboxPanel { JPanel comboboxPanel = new JPanel; comboboxPanel.setLayout); StateBarCompColleague stateBarComp = new StateBarCompColleague; TextFieldCompColleague textFieldComp = new TextFieldCompColleague; DefaultListModel<String> listModel = new DefaultListModel<>; listModel.addAll); ListCompColleague listComp = new ListCompColleague; ComboboxCompMediator comboboxCompMediator = new ComboboxCompMediator; textFieldComp.setComboboxCompMediator; listComp.setComboboxCompMediator; comboboxPanel.add; comboboxPanel.add; comboboxPanel.add; return comboboxPanel; } public static void main { CompLibV2 compLib = new CompLibV2; compLib.init; }}
ComboboxCompMediator.java:中介者角色,实现类
package com.geekarchitect.patterns.mediator.demo03;import lombok.Data;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.swing.*;@Datapublic class ComboboxCompMediator{ private static final Logger LOG = LoggerFactory.getLogger; private final TextFieldCompColleague textFieldCompColleague; private final ListCompColleague listCompColleague; private final StateBarCompColleague stateBarCompColleague; public ComboboxCompMediator { this.textFieldCompColleague = textFieldCompColleague; this.listCompColleague = listCompColleague; this.stateBarCompColleague = stateBarCompColleague; } public void setStateBarText { this.stateBarCompColleague.setText; } public void setTextFiledText { this.textFieldCompColleague.setText; } public void filterList { String currText = this.textFieldCompColleague.getText; LOG.info; SwingUtilities.invokeLater { @Override public void run { ListModel<String> listModel = ComboboxCompMediator.this.listCompColleague.getLIST_MODEL; DefaultListModel<String> filteredListModel = new DefaultListModel<>; if )) { filteredListModel = listModel; } else { for ; i++) { String item = listModel.getElementAt; if ) { filteredListModel.addElement; } } } ComboboxCompMediator.this.listCompColleague.setModel; ComboboxCompMediator.this.listCompColleague.repaint; } }); }}
ListCompColleague.java:同事角色,自定义列表框组件
package com.geekarchitect.patterns.mediator.demo03;import lombok.Data;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.swing.*;import javax.swing.event.ListSelectionEvent;import javax.swing.event.ListSelectionListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;@Datapublic class ListCompColleague extends JList<String> { private static final Logger LOG = LoggerFactory.getLogger; private ComboboxCompMediator comboboxCompMediator; private DefaultListModel<String> LIST_MODEL; public ListCompColleague { super; this.LIST_MODEL = LIST_MODEL; setModel; this.setLayoutOrientation; this.setSelectionMode; this.initListener; } public void initListener { this.addFocusListener; this.addListSelectionListener; } private void addListSelectionListener { this.addListSelectionListener { @Override public void valueChanged { String selectedValue = ListCompColleague.this.getSelectedValue; if ) { LOG.info; comboboxCompMediator.setStateBarText; comboboxCompMediator.setTextFiledText; } } }); } private void addFocusListener { this.addFocusListener { @Override public void focusGained { comboboxCompMediator.setStateBarText; } @Override public void focusLost { } }); }}
StateBarCompColleague.java:同事角色,自定义状态栏组件
package com.geekarchitect.patterns.mediator.demo03;import javax.swing.*;public class StateBarCompColleague extends JLabel { public StateBarCompColleague { super.setText; }}
TextFieldCompColleague.java:同事角色,自定义文本框组件
package com.geekarchitect.patterns.mediator.demo03;import lombok.Data;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.swing.*;import javax.swing.event.DocumentEvent;import javax.swing.event.DocumentListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;@Datapublic class TextFieldCompColleague extends JTextField { private static final Logger LOG = LoggerFactory.getLogger; private ComboboxCompMediator comboboxCompMediator; public static final String TIP = "请输入..."; public TextFieldCompColleague { super; this.initListener; } public void initListener { addFocusListener; addDocumentListener; } private void addDocumentListener { this.getDocument.addDocumentListener { @Override public void insertUpdate { comboboxCompMediator.setStateBarText; comboboxCompMediator.filterList; } @Override public void removeUpdate { comboboxCompMediator.setStateBarText; comboboxCompMediator.filterList; } @Override public void changedUpdate { comboboxCompMediator.setStateBarText; comboboxCompMediator.filterList; } }); } private void addFocusListener { this.addFocusListener { @Override public void focusGained { comboboxCompMediator.setStateBarText; if )) { TextFieldCompColleague.this.setText; } } @Override public void focusLost { if )) { TextFieldCompColleague.this.setText; } } }); }}
案例点评
这版代码,采用了中介者设计模式,每个组件的代码大大简化,相互之间的依赖关系,由原来组件之间的“多对多”依赖关系,简化为所有组件与中介者角色ComboboxCompMediator之间“一对多”的依赖关系。
下面我们开始看中介者模式的定义。
中介者模式定义解析
Define an object that encapsulates how a set of objects interact.Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
—— GOF《Design Patterns: Elements of Reusable Object-Oriented Software》
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其松耦合,而且可以独立地改变它们之间的交互。
——GOF《设计模式:可复用面向对象软件的基础》
中介者模式概念比较简单,关键词是中介对象和对象交换。
中介对象
中介对象,大家都习以为常,如果深入思考一下,中介对象有哪些特征。我认为有以下几点。
1,非必须的
以下载软件为例,在没有苹果“应用商店”类似的中介对象之前,事情也是可以办理的,只不过需要到各个软件的官方网站下载。对于我们来说可能麻烦一些。
2,不自己造轮子
中介的主要宗旨,是提高相关参与者的效率,但他自身不会造轮子,就好像苹果的“应用商店”不会自己制作自己的应用软件一样。在中介者模式中,中介者一般主要负责信息传递。
对象交互
在中介者模式中,中介者主要负责的是什么工作,这是要特别注意的,苹果的“应用商店”是为了让我们下载应用软件,房屋中介是为了我们买房子方便。而中介者模式中的中介者,主要目的是为了封装对象之间的交互,而对象之间的交互一般就体现在访问属性,调用方法。
总结一下,中介者模式,就是在原有的系统中,增加一个中介者角色,来封装原有对象之间的交互,从而让对象之间不需要显式的相互引用,或者说相互依赖,从而达到对象之间的松耦合,同时也方便我们独立的改变对象之间的交互。
进一步说,中介者模式,其实就是把对象之间多对多的依赖关系,简化为一对多的依赖关系,这里面的中介者就是“一”方,而原有的对象,就是“多”方。
REIS分析模型解析中介者模式
REIS模型是我总结的分析设计模式的一种方法论,主要包括场景,角色,交互,效果四个要素。
角色
角色,一般为设计模式出现的类,或者对象。每种角色有自己的职责。
在中介者模式中,原著中定义了四种角色,如下图所述,分别是中介者接口和中介者具体类和同事接口和同事具体类。
以我的观点,在这个设计模式中,区分角色的接口和具体类,没有实际意义。所以,我认为,中介者模式,有两种角色,分别是中介者角色,同事角色。
中介者角色
中介者角色是这个设计模式的核心,他的职责,就是封装原来存在于各个对象之间的交互。把原来对象之间的“多对多”的依赖关系,简化为“一对多”关系,而中介者就是“一对多”关系中的一方。
同事角色
同事角色,作者为什么起这个名字,英文Colleague,中文是同事,同僚的意思,按照同事的原意,是包括领导和下属的,但是通过我对中介者模式相关案例的观察,以及对目前多层软件开发架构的理解,这里的同事角色,应该更侧重在同一层,或者同一级别的对象上,而不是上下两层的对象之间。也就是中介者角色中的同事对象,如果在多层架构中,应该大多数情况下,属于同一个层的。而另外一个与中介者模式相似的门面模式,则是解决层与层之间的依赖关系。我们后面分享这个门面设计模式时,再细聊。
为什么没有客户方角色?
中介者模式,GOF的原著中,没有客户方角色,同时,我也感觉,在这个设计模式里面,好像没有客户方角色存在的价值。中介者模式的所有角色,自成一体,中介者模式产生的根源,是为了解决模块中各个对象之间的依赖关系,没有对外交互的需要,所以没有客户方角色存在的价值。
交互
交互,是指设计模式中,各种角色是如何交互的,一般用UML中的序列图,活动图来表示。简单的说就是角色之间是如何配合,完成设计模式的使命的。
对于中介者模式,他的目的就是为了解决对象之间的交互问题的,它的交互也很简单,所有同事角色之间,原则上不能有直接依赖关系,只能依赖中介者。而中介者,则需要依赖所有的同事角色。
场景
场景,也就是我们在什么情况下,遇到了什么问题,需要使用某个设计模式。
中介者模式,如我开篇所说的,“技可进乎道”,因为它的思想太基础了,反而导致我们虽然不自觉的使用了它,但是又不自知,很多设计模式中,都有中介者模式的思想存在,如果非要说何时使用中介者模式,一个比较简单的方法,就是看看对象之间是否存在多对多依赖关系,如果大量存在,则需要使用中介者模式进行简化。
效果
效果,使用该设计模式之后,达到了什么效果,有何意义,当然,也可以说说它的缺点,或者风险。
中介者模式的效果很明显,简化了同事角色之间的依赖关系,但是随着而来的负面效果也很明显,就是中介者角色,可能会比较复杂,不容易维护。这个是要特别注意的。
总结一下,基于REIS分析模型,中介者模式由两个角色组成,分别是中介者角色,同事角色,它的宗旨是,通过中介者角色,将同事角色之间“多对多”的依赖关系,变成同事与中介之间的“一对多”关系,实现同事角色之间关系的解耦合。
通用代码和类图
相关代码,大家到我的github上下载即可。
下期预告
中介者模式,我们就分享到这里,GOF23个设计模式中,行为型设计模式占了22个,我们已经全部分享完毕,后面我们除了继续分享结构型设计模式,还要对已经分享的设计模式,分享其在开源软件中的使用情况,帮助大家在自己的项目中,进一步落地设计模式。
极客架构师,专注架构师成长,我们下期见。
海外精品引流脚本–最强海外引流
唯一TG:https://t.me/Facebook181818
更多海外引流脚本方案
如果你需要脚本演示、部署咨询或海外获客方案,可以通过下面入口继续查看。
