層次風格
層次系統
–在層次系統中,系統被組織成若干個層次,每個層次由一系列組件組成
–下層組件向上層組件提供服務
–上層組件被看作是下層組件的客戶
§系統中的每一層都要承擔兩個角色。
–首先,它要爲結構中的上層提供服務;
–其次,它要作爲結構中下面層次的客戶,調用下層提供的功能函數。
–最高層和最低層例外。
基本組件:各層次內部包含的組件
§連接件:層間的交互協議
§拓撲結構:分層
§拓撲約束:對相鄰層間交互的約束
–集中式部署(Mainframe)
–分佈式部署(Distributed)
優點:
–支持基於抽象程度遞增的系統設計,有利於設計者對一個複雜
系統進行分解;
–局部依賴性,因爲每一層至多和相鄰的上下層交互,因此功能
的改變通常影響相鄰的上下層;
–可複用性,如果某獨立層保證了功能的完整性並且提供了文檔
化的接口,便可在多個語境中複用。
–可替換性,只要提供的服務接口定義不變,同一層的不同實現
可以交換使用。這樣,就可以定義一組標準的接口,而允許各
種不同的實現方法。
–對標準化的支持。清晰定義並且廣泛接受的抽象層次能夠促進
實現標準化的任務和接口開發,同樣接口的不同實現能夠互換
使用。
–可測試性。具有定義明確的層接口以及交換層接口的各個實現
的能力提高了可測試性。
缺點:
並不是每個系統都可以很容易地劃分爲分層的模式,甚至即使一個系統的邏輯結構是層次化的,出於對系統性能的考慮,系統設計師不得不把一些低級或高級的功能綜合起來;
§效率的降低:
–由分層風格構成的系統,運行效率往往低於整體結構。
–在上層中的服務如果有很多依賴於最底層,則相關的數據必須通過一些中間層的若干次轉化,才能傳到;
§很難找到合適的、正確的層次抽象方法:
–層數太少,分層不能完全發揮這種風格的可複用性、可更改性和可移植性上的潛力。
–層數過多,則引入不必要的複雜性和層間隔離冗餘以及層間傳輸開銷。
–目前,沒有可行的廣爲人們所認可的層粒度的確定和層任務的分配方法。
程序:
第一層爲用戶圖形界面層
importjava.awt.*;
importjava.util.*;
importjavax.swing.*;
importjava.awt.event.*;
importcom.sun.java.swing.plaf.windows.*;
public class TestingGUI extendsJPanel{
private JTextArea txtTestInfo, txtTestcase;
private JLabel lblTestcases;
private JPanel buttonPanel;
private JComboBox cmbTestcases;
private static final String CASE_BUBBLE= "TC1-Test BubbleSort";
private static final String CASE_HEAP= "TC2-Test Heap Sort";
private static final String CASE_INSERTION= "TC3-Test InsertionSort";
private static final String EXECUTE = "Execute";
private static final String EXIT = "Exit";
public TestingGUI(){
txtTestInfo=new JTextArea("Test outputfrom source shown here\n", 6, 20);
txtTestInfo.setLineWrap(true);
txtTestcase = new JTextArea("Testcaseinfo and test validation shown here\n", 4, 15);
txtTestcase.setLineWrap(true);
buildUpScrollGUI();
}
private void buildUpScrollGUI(){
setUpButtonPanel();
JScrollPane btnPane = new JScrollPane(buttonPanel);
JScrollPane textPane = newJScrollPane(txtTestcase);
textPane.setMinimumSize(new Dimension(250,150));
JScrollPane testDataPane = newJScrollPane(txtTestInfo);
JSplitPane upSplitPane = newJSplitPane(JSplitPane.HORIZONTAL_SPLIT);
upSplitPane.setLeftComponent(btnPane);
upSplitPane.setRightComponent(testDataPane);
JScrollPane downPane = newJScrollPane(textPane);
Dimension minimumSize = new Dimension(130,100);
btnPane.setMinimumSize(minimumSize);
textPane.setMinimumSize(new Dimension(100,100));
upSplitPane.setDividerLocation(270);
upSplitPane.setPreferredSize(newDimension(500, 300));
JSplitPane bigSplitPane = newJSplitPane(JSplitPane.VERTICAL_SPLIT, upSplitPane, downPane);
bigSplitPane.setDividerLocation(190);
add(bigSplitPane);
setSize(new Dimension(500, 400));
setVisible(true);
}
private void setUpButtonPanel(){
lblTestcases = new JLabel("TestCases:");
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 = newBtnListener();
// add action Listener
executeBtn.addActionListener(objButtonHandler);
exitButton.addActionListener(objButtonHandler);
buttonPanel = new JPanel();
GridBagLayout gridbag = newGridBagLayout();
buttonPanel.setLayout(gridbag);
GridBagConstraints gbc = newGridBagConstraints();
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]+" ");
}
public void showErrors(String err){
txtTestcase.append(err+"\n");
}
public String getSelectedTestcase() {
return (String)cmbTestcases.getSelectedItem();
}
class BtnListener implements ActionListener{
private Testcase test;
private String selectedTestcase;
public void actionPerformed(ActionEvent e){
String searchResult = null;
int[] output=null;
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();
elseif(selectedTestcase.equals(CASE_INSERTION))
test = new TestcaseInsertion();
output = test.execute(3000);
showTestInfo(output);
}
showErrors(selectedTestcase);
boolean result =ResultVerification.isResultCorrect(output );
showErrors("No Error found =" +result);
long timeTaken = test.getTimeTaken();
showErrors("Testing Time takes =" + timeTaken+"\n");
}
} // End of class BtnListener
private static void createAndShowGUI(){
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("LayeredArchitecture- Software Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TestingGUI newContentPane = newTestingGUI();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
static public void main(String argv[]) {
javax.swing.SwingUtilities.invokeLater(newRunnable() {
public void run() {
createAndShowGUI();
}
});
}
}
public class ResultVerification{
static boolean flag = true;
public static booleanisResultCorrect(int[] arr){
for(int k=0; k<arr.length-1; k++){
if(arr[k] > arr[k+1]){
flag=false;
System.out.println("error "+ k);
//break;
}
}
return flag;
}
}
第二層爲測試案例層,包括軟件測試工程師所編寫的測試案例
publicinterface Testcase{
public abstract int[] execute(int len);
public abstract long getTimeTaken();
}
class Context {
SortAlgorithm alg;
// Constructor
public Context(SortAlgorithm alg) {
this.alg = alg;
}
public int[] sortIntArray(int[] a) {
return this.alg.sort(a);
}
}
import java.util.Random;
public class IntegerArrGenerator{
public static int[] generateInput(int len){
int[] input= new int[len];
Random r = new Random();
for(int m=0; m< len; m++){
input[m] = r.nextInt(len);
}
return input;
}
}
import java.util.*;
public class TestcaseBubbleimplements Testcase{
private long startTime;
private long timeTaken=0;
public int[] execute(int len) {
startTime = System.currentTimeMillis();
int[] input =IntegerArrGenerator.generateInput(len);
SortAlgorithm sa = new BubbleSort();
Context context = new Context(sa);
int[] intArray = context.sortIntArray(input);
timeTaken =System.currentTimeMillis() - startTime;
return intArray;
}
public long getTimeTaken(){
return timeTaken;
}
}
import java.util.*;
public class TestcaseHeapimplements Testcase{
//static long time;
private long startTime;
private long timeTaken=0;
public int[] execute(int len){
startTime= System.currentTimeMillis();
int[]input = IntegerArrGenerator.generateInput(len);
SortAlgorithmsa = new HeapSort();
Contextcontext = new Context(sa);
int[]intArray = context.sortIntArray(input);
timeTaken= System.currentTimeMillis()-startTime;
return intArray;
}
public long getTimeTaken(){
return timeTaken;
}
}
import java.util.*;
public class TestcaseInsertionimplements Testcase{
private long startTime;
private long timeTaken=0;
public int[] execute(int len){
startTime = System.currentTimeMillis();
int[] input =IntegerArrGenerator.generateInput(len);
SortAlgorithm sa = new InsertSort();
Context context = new Context(sa);
int[] intArray = context.sortIntArray(input);
timeTaken =System.currentTimeMillis()-startTime;
return intArray;
}
public long getTimeTaken(){
return timeTaken;
}
}
第三層爲被測試軟件層(排序算法)
public interface SortAlgorithm {
int[] sort(int[] nums);
}
public class BubbleSort implementsSortAlgorithm {
public int[] sort(int[] nums){
for(int i = nums.length; --i >= 0;)
for(int j = 0; j < i; j++){
if(nums[j] > nums[j + 1]){
//exchange nums[j+1] withnums[j]
int T =nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = T;
}
}
return nums;
}
}
public class HeapSort implementsSortAlgorithm{
public int[] sort(int nums[ ]) {
for(int i=nums.length; i>1; i--){
buildBinaryHeapTree(nums, i -1);
swapLeadingNodeWithLastNode(nums, i - 1);
}
return nums;
}
public void buildBinaryHeapTree(intarray[], int arrayBound){
int leftChild, rightChild, biggerChild,temp;
int root = (arrayBound-1)/2;
// Find the bigger child index
for(int i=root; i>=0; i--) {
leftChild = (2*i)+1;
rightChild = (2*i)+2;
if((leftChild <= arrayBound)&& (rightChild <= arrayBound)){
if(array[rightChild] >=array[leftChild])
biggerChild =rightChild;
else
biggerChild = leftChild;
}
else{
if(rightChild >arrayBound)
biggerChild = leftChild;
else
biggerChild = rightChild;
}
//swap the integer contained inthe bigger child index
//with that in the currentparent node
if(array[i] <array[biggerChild]){
temp = array[i];
array[i] =array[biggerChild];
array[biggerChild] = temp;
}
}
return;
}
publicstatic void swapLeadingNodeWithLastNode(int array[], int arrayBound){
int temp;
temp = array[0];
array[0] = array[arrayBound];
array[arrayBound] = temp;
return;
}
}
public class InsertSortimplements SortAlgorithm {
public int[] sort(int[] nums){
for (int i = 1; i < nums.length;i++){
int j = i;
int numToBeInserted = nums[i];
while ((j > 0) &&(nums[j-1] > numToBeInserted) ) {
nums[j] = nums[j-1];
j--;
}
nums[j] = numToBeInserted;
}
return nums;
}
}