一.概念说明
先这样理解一个项目,一个项目是由多个子程序(完成各种功能的类)组成,而一个子程序又是由多个模块(各种方法)组成。 这样,低耦合可以理解成项目中子程序之间的联系程度较低,而高耦合则是某个子程序中模块之间的联系程度较紧密。 高内聚和低耦合 是OOP编程典型的特点,也是评价设计模式好坏的重要标准。
这里必须提到 封装和继承 的问题,封装和继承是OOP编程显著的优点,能够大量的简化程序员的工作,让程序变得简单明了。 定义这里不再赘述,且谈点封装和继承的作用所在。
封装,形象的说就是将 可以完成某些功能的程序 给封起来。这样 在使用该程序的时候就不必 在写程序之前阅读几个小时了。 只需调用 该程序留下的接口便可,大大降低了程序的复杂程度。好比 使用电视机的时候,不用打开盒子开构造,只需遥控器便可。 而接口的使用过程就是继承。 如此这般,程序的低耦合性就出来了,无论工程怎么要求,都不必改变已封装的程序,这便是低耦合的好处,否则,工程的要求一旦有小小的改变,也会使得程序要大规模改动才能解决。
二.代码示例
这里的示例内容是一个界面程序,
分析: 程序可以分成 界面部分 和 信息处理部分, 然后再将信息添加到界面上显示出来。
下面先给非低耦合性的程序(仅为示例程序,用于说明问题。程序未完整)
总共3个类: 界面类(class MainUI) 信息类(class Msg)即显示的信息 信息显示的实现类(class ShowMsg)
1.类 class MainUI
this.setTitle("显示界面");
this.setSize(200, 400);
this.setLayout(new FlowLayout());
//Tree节点对象
rootNode = new DefaultMutableTreeNode();// 数据结构 树 中的通用节点
javax.swing.tree.DefaultTreeModel tm = new javax.swing.tree.DefaultTreeModel(rootNode);
//创建界面上 Tree对象
tree = new JTree();
tree.setModel(tm);
this.add(tree);
this.setDefaultCloseOperation(3);
this.setVisible(true);
class MainUI类说明,界面类中包含有 Tree对象的创建。如果要 信息显示要另外的要求,则必须要改变此类
2.类class Msg
private int id;
private String content;
public String toString(){ return content; }
public void setId(int id){ this.id = id; }
public int getId(){ return id; }
public void setContent(String content){ this.content = content; }
class Msg说明: 对显示的信息进行定义,超简单。
3.类class ShowMsg
private DefaultMutableTreeNode treeNode;
//构造器传入 rootNode
public NetConnector(DefaultMutableTreeNode treeNode){ this.treeNode = treeNode;}
public void run(){
int t=0;
while(true){
t++;
try{
Thread.sleep(2000);
}catch(Exception ef){ ef.printStackTrace(); }
//信息模拟
Msg ms = new Msg();
ms.setId(t);
ms.setContent("第"+t+"条消息");
//创建叶节点 ,并连到跟节点上
DefaultMutableTreeNode node = new DefaultMutableTreeNode(ms);
treeNode.add(node);
//刷新界面
javax.swing.SwingUtilities.updateComponentTreeUI(MainUI.tree);
}
}
class ShowMsg说明:该类模拟了信息,并显示到界面上。注意:该程序中有一个构造器传参,如果该项目需要改变,构造器传参会大大增加程序改变的规模。该项目示例中,仅3个类,一个构造器传参,当类增多到7,8个甚至更多时,若还是这样的网型结构,那就比较悲剧了。一旦一个地方出错,会带出一连串错误。另外,如果要对项目功能进行小小的改变,那几乎所有类都要变化,规模超大。
接下来给出低耦合性的程序示例
分两个包:
第一个包(有2个类,1个接口) 提供处理信息的接口和显示信息的功能
1.接口 interface IMsgListener 自定义的接口,用于处理信息
//处理信息的方法
public void msgAction(Msg m);
interface IMsgListener 说明 :定义了一个处理信息的接口。
2.类 class Msg 信息类,同上段代码示例
3.类 class ShowMsg 信息显示的实现类
private List<IMsgListener> liListen = new ArrayList<IMsgListener>();
public void addliListen(IMsgListener IMsg){
liListen.add(IMsg);
}
public void run(){
int count=0;
while(true){
count++;
//信息模拟
Msg msg=new Msg();
msg.type=(byte)(count/3);
msg.content="这是收到的消息内容-"+count;
for(int i=0;i<liListen.size();i++){
IMsgListener im = liListen.get(i);
im.msgAction(msg);
}
try{
Thread.sleep(1000);
}catch(Exception ef){
ef.printStackTrace();
}
}
class ShowMsg说明:该类大部分与上例相似,但是这里创建了一个List,存放 信息处里的实现类(下一个包中出现)对象,这和 监听机制有些相似。
第二个包(有2个类) 实现信息的处理 和 显示界面
1类 class ImpMsgLabel extends JLabel implements IMsgListener 信息处理的实现类 继承JLabel,实现IMsgListener 接口 (此例中简化 采用JLable 不使用上例中的JTree)
//传给父类构造器
public ImpMsgLabel(String text){ super(text); }
//将信息加到JLable上
public void msgAction(Msg m) {
this.setText(m.content);
}
class ImpMsgLabel说明:实现自定义的接口,处理信息 。类似监听器的实现类,实现对信息的监听。
2类 class MainUI
public void setUI(){
this.setTitle("显示界面");
this.setSize(200, 300);
this.setLayout(new FlowLayout());
//给界面加JLable 同时实现监听
ImpMsgLabel ILable = new ImpMsgLabel("显示");
this.add(ILable);
this.setDefaultCloseOperation(3);
this.setVisible(true);
//调用线程,添加信息到界面
CommThread ct = new CommThread();
ct.addliListen(ILable);//添加队列对象,用于界面显示信息
ct.start();
}
class MainUI 说明: 用来显示界面,与前一个包的耦合程度达到最小,仅仅掉用线程,并执行,若要对程序进行改动,则不会牵连过大,各个模块自行改动便可。
总结: 以上两个代码示例的对比 突出了低耦合的优越性。低耦合的程序生存力强,禁得住折腾,而且分块简单明了。若要进行改进,明显低耦合的程序操作性更强。