分享
 
 
 

爪哇语言结构性模式之变压器模式介绍(下)

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

抽象类WindowAdapter是变压器模式的一个例子

抽象类WindowAdapter是为接受视窗的事件而预备的。此抽象类内所有的方法都是空的。 使用此类可以很方便地创立listener对象。置换(Override)你所感爱好的那个事件所对应的方法。 假如你不使用此抽象类,那么你必然规律要实现WindowsListener接口,而那样你就不得不实现所有接口中的方法, 即便是你不需要的事件所对应的方法,你也要给出一个空的方法,而这显然不方便。

显然,抽象类WindowAdapter的目标接口可以选得与源接口一样,而不影响效果。 这就解释了为什么目标接口不出现在WindowAdapter类图(见下面)里。

图3. 本例子SwingUI类与WindowAdapter实例变压器模式的类图定义

SwingUI类的代码如下。

import java.awt.Color;

import java.awt.BorderLayout;

import java.awt.event.*;

import javax.swing.*;

class SwingUI extends JFrame implements ActionListener

{

JLabel text, clicked;

JButton button, clickButton;

JPanel panel;

PRivate boolean m_clickMeMode = true;

Public SwingUI()

{

text = new JLabel("我很兴奋!");

button = new JButton("理我");

button.addActionListener(this);

panel = new JPanel();

panel.setLayout(new BorderLayout());

panel.setBackground(Color.white);

getContentPane().add(panel);

panel.add(BorderLayout.CENTER, text);

panel.add(BorderLayout.SOUTH, button);

}

public void actionPerformed(ActionEvent event)

{

Object source = event.getSource();

if (m_clickMeMode)

{

text.setText("我很烦!");

button.setText("别理我");

m_clickMeMode = false;

}

else

{

text.setText("我很兴奋!");

button.setText("理我");

m_clickMeMode = true;

}

}

public static void main(String[] args)

{

SwingUI frame = new SwingUI();

frame.setTitle("我");

WindowListener listener = new WindowAdapter()

{

public void windowClosing(WindowEvent e)

{

System.exit(0);

}

};

frame.addWindowListener(listener);

frame.pack();

frame.setVisible(true);

}

}

代码清单7. SwingUI类的源代码。红色的代码就是使用WindowAdapter的无名内部类。

显然,由于无名内部类是继续自WindowAdapter抽象类,因此只需置换(override)掉我们需要的方法, 即windowClosing()而不必操心WindowListener的其它方法。

本例子在运行时的样子:

图4. SwingUI类在运行时的样子。单击命令键“理我”就变成下图的样子。

图5. 再单击命令键“别理我”就会回到前图的样子

利用变压器模式指方为圆

中国古代有赵高指鹿为马的故事。鹿与马有很多相似之处,没见过的人本就分辨不清,指一指可能没什么大不了的。 指方为圆是否太过?非也。本例就是要指方为圆,需要的只是变压器模式这个魔术手指(Magic Finger)。

变压器模式在本例子的类图如下。

图6. 指方为圆的变压器模式类图

package com.javapatterns.adapter.cube2ball;

public class Cube

{

public Cube(double width)

{

this.width = width;

}

public double calculateVolume()

{

return width * width * width;

}

public double calculateFaceArea()

{

return width * width;

}

public double getWidth()

{

return this.width;

}

public void setWidth(double width)

{

this.width = width;

}

private double width;

}

代码清单8. Cube类的源代码。。

package com.javapatterns.adapter.cube2ball;

public interface BallIF

{

double calculateArea();

double calculateVolume();

double getRadius();

void setRadius(double radius);

}

代码清单9. BallIF接口的源代码。

package com.javapatterns.adapter.cube2ball;

public class MagicFinger implements BallIF

{

public MagicFinger(Cube adaptee)

{

super();

this.adaptee = adaptee;

radius = adaptee.getWidth();

}

public double calculateArea()

{

return PI * 4.0D * ( radius * radius );

}

public double calculateVolume()

{

return PI * 4.0D/3.0D * ( radius * radius * radius );

}

public double getRadius()

{

return radius;

}

public void setRadius(double radius)

{

this.radius = radius;

}

private double radius = 0;

private static final double PI = 3.14D;

private Cube adaptee;

}

代码清单10. MagicFinger类的源代码。

假如读者还记得中学的数学的话,应该可以看出,我们的指方为圆系统其实还是有道理的。它接受一个正方体, 返还此正方体的内切球,也就是能放进此正方体的最大的球。

显然,本例子里,我们使用的是实例形式的变压器模式。这样做的好处是,假如一旦我们决定不仅要支持正方体, 而且要支持四面体等多面体,我们可以使用同一个MagicFinger类,而不必针对每一个多面体都建立一个MagicFinger类。 这样也比较符合“魔术手指”这个名字。

关于模式实现的讨论

本模式在实现时有以下这些值得注重的地方:

第一、目标接口可以省略。此时,目标接口和源接口实际上是相同的。 由于源是一个接口,而变压器类是一个类(或抽象类),因此这种做法看似平庸而并不平庸, 它可以使客户端不必实现不需要的方法。这一点已经在WindowAdapter的例子里做了详尽的分析。

第二、变压器类可以是抽象类。这已经在WindowAdapter的例子里看到了。实际上,WindowAdapter的例子过于简单。 实际的情形里,你可能想给出一些实方法。

第三、带参数的变压器模式。使用这种办法,变压器类就不必,有时可能不能是源类的子类。 变压器类根据参数返还一个合适的实例给客户端。

问答题

第1题、请做一个小猫(kittie)的实类,并实现miao(),catchRat(),run(),sleep()等方法。 再做一个小狗(doggie)的接口,要求有wao(),fetchBall(),run(),sleep()等方法。

现在你的女朋友想要一只小狗,可是你只找到的一只小猫。请用变压器模式把小猫“适配成”小狗, 让你的女朋友满足。(提示:量力而为。)

第2题、请指出第一题的解答所使用的是那一种形式的变压器模式。

第3题、笔者在许多场合给各种不同水准的专业人士作过各种编程模式的介绍,发现参加OOP开发工作的不同时间长短的人, 对不同的模式理解接受的速度有所不同。唯独在讲过这个男朋友与小狗小猫的例子后,大家对变压器模式的理解都很准确。 让笔者百思不得其解。你知道这是怎样回事吗?

第4题、请讲一讲使用实例形式的变压器模式和使用类形式的变压器模式在第一题的解决上有何影响。

问答题答案

第1题、根据提示,我们可以量力而为。因此,我们将把miao()“适配成”wao(),catchRat()“适配成”fetchBall(), run(),sleep()不变。源代码如下:

图7. 男朋友小狗适配器的类图。

package com.javapatterns.adapter.kittie2doggie;

public interface Doggie

{

void wao();

void fetchBall();

void run();

void sleep();

void setName(String name);

String getName();

}

代码清单11. SwingUI类的源代码。红色的代码就是使用WindowAdapter的无名内部类。

package com.javapatterns.adapter.kittie2doggie;

public class Kittie {

public void miao(){}

public void catchRat() {

}

public void run() {

}

public void sleep() {

}

public String getName(){ return name; }

public void setName(String name){ this.name = name; }

}

代码清单12. SwingUI类的源代码。红色的代码就是使用WindowAdapter的无名内部类。

package com.ja

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有