概述
实验内容截取
实验目的
(1)理解基于事件的隐式调用软件体系结构、层次软件体系结构的原理
(2)掌握事件的隐式调用软件体系结构、层次软件体系结构的实例
(3)事件的隐式调用软件体系结构、层次软件体系结构的编程实现
实现内容
2.层次软件体系结构
基于层次软件体系结构的软件测试系统。
第一层为用户图形界面层
public class TestingGUI extends JPanel {
private JTextArea txtTestInfo, txtTestcase;
private JLabel lblTestcases;
private JPanel buttonPanel;
private JComboBox cmbTestcases;
private static final String CASE_BUBBLE = "TC1-Test Bubble Sort";
private static final String CASE_HEAP = "TC2-Test Heap Sort";
private static final String CASE_INSERTION = "TC3-Test Insertion Sort";
private static final String EXECUTE = "Execute";
private static final String EXIT = "Exit";
public TestingGUI() {
txtTestInfo = new JTextArea("Test output from source shown heren", 6, 20);
txtTestInfo.setLineWrap(true);
txtTestcase = new JTextArea("Testcase info and test validation shown heren", 4, 15);
txtTestcase.setLineWrap(true);
buildUpScrollGUI();
}
private void buildUpScrollGUI() {
setUpButtonPanel();
JScrollPane btnPane = new JScrollPane(buttonPanel);
JScrollPane textPane = new JScrollPane(txtTestcase);
textPane.setMinimumSize(new Dimension(250, 150));
JScrollPane testDataPane = new JScrollPane(txtTestInfo);
JSplitPane upSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
upSplitPane.setLeftComponent(btnPane);
upSplitPane.setRightComponent(testDataPane);
JScrollPane downPane = new JScrollPane(textPane);
Dimension minimumSize = new Dimension(130, 100);
btnPane.setMinimumSize(minimumSize);
textPane.setMinimumSize(new Dimension(100, 100));
upSplitPane.setDividerLocation(270);
upSplitPane.setPreferredSize(new Dimension(500, 300));
JSplitPane bigSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upSplitPane, downPane);
bigSplitPane.setDividerLocation(190);
add(bigSplitPane);
setSize(new Dimension(500, 400));
setVisible(true);
}
// ......
// ......
// 略
}
还有其他一些代码,我这里就不放出来了。。。
效果图和功能
选择排序算法,点击Execute,会随机生成指定长度的序列。并使用指定的排序算法进行排序。输出排序后的序列,排序耗时等信息。
这是软件体系结构这门课程的一个实验作业。给出例程的目的原本是让我们调试程序,从而理解程序隐含的软件体系结构。????我比较强迫症,看着这多多少少有点毛病的代码,想把它改成自己满意的样子。
例程的问题
(1)每一个Testcase的实现类的代码存在大量的重复
(2)随机生成序列、排序、校验排序结果3个操作都是耗时操作,然而这3个操作都以同步的方式放在主线程中。当数据量较大,经我测试,当数组元素个数为10万时,点击一次执行,会造成较长时间的阻塞。当快速多次点击执行,程序崩溃,界面卡住不动。
优化方案
(1)将重复代码抽离出来放到父类,只需要将实例化算法对象的操作交由子类实现即可。
(2)每一次execute操作都有独立的线程异步操作。然而这时会遇到两个问题:
①异步线程何时返回结果,返回的结果如何更新到界面?
通过事件回调的方式,解决异步线程的结果返回。
②当多次点击execute后,多个线程异步操作。当某个线程已经完成,从而回调到界面,正在在界面渲染数据,此时又一个线程完成,同时又向界面渲染数据。界面的耗时渲染,让我们看到了多线程并发的界面数据错乱现象。
只需要将渲染界面的操作放在同步代码块之内即可
修改后的代码
我只贴出我有更改的类的代码。
Testcase
package demo2.test;
public interface Testcase {
void execute(int len, EventCallback callback);
interface EventCallback {
/**
* 包含了3个操作:生成指定长度的随机数列,排序,校验排序结果是否正确
* @param sortedArr 排序好的数组
* @param costTime 排序所花费的时间(不包括生成随机数列的时间和校验排序结果的时间)
* @param isCorrect 排序结果是否正确
*/
void onExecuted(int[] sortedArr, long costTime, boolean isCorrect);
}
}
AlgorithmTestCase
package demo2.test;
import demo2.IntegerArrGenerator;
import demo2.ResultVerification;
import demo2.algorithm.SortAlgorithm;
/**
* Testcase接口的实现类,但是个抽象类。
* 实例化算法对象的操作通过抽象方法抛给子类实现
*
* @author passerbyYSQ
* @date 2020-9-15 20:47:09
*/
public abstract class AlgorithmTestCase<T extends SortAlgorithm> implements Testcase {
protected T algorithm;
protected Context context;
protected abstract T crateAlgorithm();
@Override
public void execute(int len, EventCallback callback) {
Thread th = new Thread(new GenerateAndSortInt(len, callback));
th.start();
}
class GenerateAndSortInt implements Runnable {
long startTime;
long timeTaken = 0;
int len;
int[] arr;
EventCallback callback;
public GenerateAndSortInt(int len, EventCallback callback) {
this.len = len;
this.callback = callback;
}
@Override
public void run() {
// 耗时
arr = IntegerArrGenerator.generateInput(len);
algorithm = crateAlgorithm();
context = new Context(algorithm);
// 排序。耗时
startTime = System.currentTimeMillis();
arr = context.sortIntArray(arr);
long costTime = System.currentTimeMillis() - startTime;
// 校验排序结果。耗时
boolean isCorrect = ResultVerification.isResultCorrect(arr);
callback.onExecuted(arr, costTime, isCorrect);
}
}
}
TestcaseBubble
package demo2.test;
import demo2.algorithm.BubbleSort;
public class TestcaseBubble extends AlgorithmTestCase<BubbleSort> {
@Override
protected BubbleSort crateAlgorithm() {
return new BubbleSort();
}
}
TestcaseHeap
package demo2.test;
import demo2.algorithm.HeapSort;
public class TestcaseHeap extends AlgorithmTestCase<HeapSort> {
@Override
protected HeapSort crateAlgorithm() {
return new HeapSort();
}
}
TestcaseInsertion
package demo2.test;
import demo2.algorithm.InsertSort;
public class TestcaseInsertion extends AlgorithmTestCase<InsertSort> {
@Override
protected InsertSort crateAlgorithm() {
return new InsertSort();
}
}
TestingGUI
package demo2;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import demo2.test.Testcase;
import demo2.test.Testcase.EventCallback;
import demo2.test.TestcaseBubble;
import demo2.test.TestcaseHeap;
import demo2.test.TestcaseInsertion;
public class TestingGUI extends JPanel {
private JTextArea txtTestInfo, txtTestcase;
private JLabel lblTestcases;
private JPanel buttonPanel;
private JComboBox cmbTestcases;
private static final String CASE_BUBBLE = "TC1-Test Bubble Sort";
private static final String CASE_HEAP = "TC2-Test Heap Sort";
private static final String CASE_INSERTION = "TC3-Test Insertion Sort";
private static final String EXECUTE = "Execute";
private static final String EXIT = "Exit";
public TestingGUI() {
txtTestInfo = new JTextArea("Test output from source shown heren", 6, 20);
txtTestInfo.setLineWrap(true);
txtTestcase = new JTextArea("Testcase info and test validation shown heren", 4, 15);
txtTestcase.setLineWrap(true);
buildUpScrollGUI();
}
private void buildUpScrollGUI() {
setUpButtonPanel();
JScrollPane btnPane = new JScrollPane(buttonPanel);
JScrollPane textPane = new JScrollPane(txtTestcase);
textPane.setMinimumSize(new Dimension(250, 150));
JScrollPane testDataPane = new JScrollPane(txtTestInfo);
JSplitPane upSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
upSplitPane.setLeftComponent(btnPane);
upSplitPane.setRightComponent(testDataPane);
JScrollPane downPane = new JScrollPane(textPane);
Dimension minimumSize = new Dimension(130, 100);
btnPane.setMinimumSize(minimumSize);
textPane.setMinimumSize(new Dimension(100, 100));
upSplitPane.setDividerLocation(270);
upSplitPane.setPreferredSize(new Dimension(500, 300));
JSplitPane bigSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upSplitPane, downPane);
bigSplitPane.setDividerLocation(190);
add(bigSplitPane);
setSize(new Dimension(500, 400));
setVisible(true);
}
private void setUpButtonPanel() {
lblTestcases = new JLabel("Test Cases:");
cmbTestcases = new JComboBox();
cmbTestcases.addItem(CASE_BUBBLE);
cmbTestcases.addItem(CASE_HEAP);
cmbTestcases.addItem(CASE_INSERTION);
// Create the open button
JButton executeBtn = new JButton(EXECUTE);
executeBtn.setMnemonic(KeyEvent.VK_S);
JButton exitButton = new JButton(EXIT);
exitButton.setMnemonic(KeyEvent.VK_X);
BtnListener objButtonHandler = new BtnListener();
// add action Listener
executeBtn.addActionListener(objButtonHandler);
exitButton.addActionListener(objButtonHandler);
buttonPanel = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
buttonPanel.setLayout(gridbag);
GridBagConstraints gbc = new GridBagConstraints();
buttonPanel.add(lblTestcases);
buttonPanel.add(cmbTestcases);
buttonPanel.add(executeBtn);
buttonPanel.add(exitButton);
gbc.insets.top = 5;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 0;
gbc.gridy = 0;
gridbag.setConstraints(lblTestcases, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 0;
gridbag.setConstraints(cmbTestcases, gbc);
gbc.anchor = GridBagConstraints.EAST;
gbc.insets.left = 2;
gbc.insets.right = 2;
gbc.insets.top = 25;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 0;
gbc.gridy = 7;
gridbag.setConstraints(executeBtn, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 7;
gridbag.setConstraints(exitButton, gbc);
}
public void showTestInfo(int[] str) {
txtTestInfo.setText("");
for (int n = 0; n < str.length; n++)
txtTestInfo.append("" + str[n] + " ");
// StringBuilder sbd = new StringBuilder("");
// for (int n = 0; n < str.length; n++) {
// sbd.append(str[n]).append(" ");
// }
// txtTestInfo.setText(sbd.toString());
}
public void showText(String err) {
txtTestcase.append(err + "n");
}
public String getSelectedTestcase() {
return (String) cmbTestcases.getSelectedItem();
}
/**
* 实现了EventCallback接口。当异步线程执行完成,会回调到这里的 onExecuted()方法
* @author passerbyYSQ
* @date 2020-9-15 20:56:02
*/
class BtnListener implements ActionListener, EventCallback {
private Testcase test;
private String selectedTestcase;
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(EXIT)) {
System.exit(1);
}
if (e.getActionCommand().equals(EXECUTE)) {
selectedTestcase = getSelectedTestcase();
if (selectedTestcase.equals(CASE_BUBBLE))
test = new TestcaseBubble();
else if (selectedTestcase.equals(CASE_HEAP))
test = new TestcaseHeap();
else if (selectedTestcase.equals(CASE_INSERTION))
test = new TestcaseInsertion();
test.execute(100000, this);
}
}
/**
* 多线程并发问题:
* 假如频繁操作,导致多个数组陆续排序好。前一个数组还没操作完界面,另一个数组
* 又开始更新界面。会导致界面的数组输出错乱。
*所以操作ui的方法需要加上synchronized限定
*/
@Override
public synchronized void onExecuted(int[] sortedArr, long costTime, boolean isCorrect) {
// 更新ui最好也不要使用主线程。
int[] output = sortedArr;
showTestInfo(output);
showText(selectedTestcase);
// 结果检验也是个费时操作,不应该放到ui更新里面做。否则会出现卡顿现象
showText("No Error found = " + isCorrect);
showText("Testing Time takes = " + costTime + "n");
}
}
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Layered Architecture- Software Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TestingGUI newContentPane = new TestingGUI();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String argv[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
最后
以上就是悲凉电话为你收集整理的经典软件体系结构风格(二):层次软件体系结构。例程代码优化!实验内容截取效果图和功能例程的问题优化方案修改后的代码的全部内容,希望文章能够帮你解决经典软件体系结构风格(二):层次软件体系结构。例程代码优化!实验内容截取效果图和功能例程的问题优化方案修改后的代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复