1. 程式人生 > >走進設計模式的世界9:我們的公司很複雜-迭代器與組合模式

走進設計模式的世界9:我們的公司很複雜-迭代器與組合模式

迭代器模式 :

提供一個方法順序訪問一個聚合物件中的各個元素,而又不暴露其內部表示。

組合模式 :

允許你將物件組成樹形結構來表現“整體/部分”的層次結構。組合能讓可以以一致的方式處理個別對象和物件組合。

設計原則:類應該只有一個改變的理由

解釋 : 迭代器允許訪問聚合的元素,而不需要暴露它的內部結構。迭代器將遍歷聚合的工作封裝進一個物件中。當使用迭代器的時候,我們依賴聚合提供遍歷。迭代器提供了一個通用的介面讓我們遍歷聚合的項,當我們編碼使用聚合的項時,就可以使用多型機制。我們應該努力讓一個類只分配一個責任。組合模式允許客戶對個別物件以及組合物件一視同仁。組合結構內的任意物件稱為元件,元件可以是組合,也可以是葉節點。在實現組合模式時,有許多設計上的折衷,你要根據需要平衡透明性和安全性。

迭代器模式樣例演示:我們有很多部門。

/**
    我們公司有很多種部門
    暫且拿出來行政部門和技術部門作比較
    技術部門是拿array儲存的人員資訊,因為要控制人員薪資,控制人員的數量。
    行政部門是拿ArrayList儲存的人員資訊,因為可以輕易的擴充套件資訊。
**/

/**
    行政部門
**/
public class XingZhengDept{
    ArrayList  employees;
    
    public XingZhengDept{
        employees = new ArrayList();
        addEmployee("行政1",3500);
        addEmployee("行政2",3400);
        addEmployee("行政3",3300);
    }
    
    public void addEmployee(String name,double salary){
        Employee e = new Employee(name,salary);
        employees.add(e);   
    }
    
    public ArrayList getEmpItems(){
        return employees;
    }
}


/**
    技術部門
**/
public class JiShuDept{
    Employee[] employees;
    int index = 0;
    static final int MAX = 3;
    public JiShuDept{
        employees = new Employee[3];
        addEmployee("技術1",3500);
        addEmployee("技術2",3400);
        addEmployee("技術3",3300);
    }
    
    public void addEmployee(String name,double salary){
        Employee e = new Employee(name,salary);
        if(index<MAX){
            employees[index]=e;
            index++;
        }else{
            System.out.println("技術已經夠多了不能再加人了!!!!");
        }
    }

    public Employee[] getEmpItems(){
        return employees;
    }
}

/**
    如果我想遍歷兩個部門的所有人員和薪資狀況,
    我就分別關注兩個訂單的返回
**/
public class Test{
    public static void main(String[]args){
        JiShuDept jishu = new JiShuDept();
        XingZhengDept xingzheng = new XingZhengDept();
        Employee[] jishus = jishu.getEmpItems();
        ArrayList xingzhengs = xingzheng.getEmpItems();
        for(Employee e:xingzhengs){
            System.out.println(e);
        }
        for(Employee e:jishus){
            System.out.println(e);
        }        
    }
}

這時候負責統計的類就分別依賴了員工list和員工陣列。接下來我們用迭代器改造這兩個部分。

 

/**
 
    先做一個技術部的迭代器

**/

public class JiShuDeptIterator implements Iterator{
    Employee[] employees;
    int index = 0;
    public JiShuDeptIterator (Employee[] employees){
        this.employees = employees; 
    }
    
    public Object next(){
        Employee e = employees[index];
        index++;
        return e;
    }
    
    public boolean hasNext(){
        if(index>=employees.length||employess[index]==null){
            return false;
        }else{
            return true;
        }
    }
    
}



/**
    技術部門
**/
public class JiShuDept{
    Employee[] employees;
    int index = 0;
    static final int MAX = 3;
    public JiShuDept{
        employees = new Employee[3];
        addEmployee("技術1",3500);
        addEmployee("技術2",3400);
        addEmployee("技術3",3300);
    }
    
    public void addEmployee(String name,double salary){
        Employee e = new Employee(name,salary);
        if(index<MAX){
            employees[index]=e;
            index++;
        }else{
            System.out.println("技術已經夠多了不能再加人了!!!!");
        }
    }
    
    /**
        因為需要使用迭代器模式,所以這種遍歷的方法棄用了。
    **/
    public Employee[] getEmpItems(){
        return employees;
    }
    
    /**
       返回一個迭代器。 
    **/
    public Iterator createIterator(){
        return new JiShuDeptIterator(employees);
    }
}


/**
    由於行政部門是用list儲存的所以不需要迭代器
**/

public class XingZhengDept{
    ArrayList  employees;
    
    public XingZhengDept{
        employees = new ArrayList();
        addEmployee("行政1",3500);
        addEmployee("行政2",3400);
        addEmployee("行政3",3300);
    }
    
    public void addEmployee(String name,double salary){
        Employee e = new Employee(name,salary);
        employees.add(e);   
    }
    
    /**
        因為需要使用迭代器模式,所以這種遍歷的方法棄用了。
    **/
    public ArrayList getEmpItems(){
        return employees;
    }

    /**
       返回一個迭代器。 
    **/
    public Iterator createIterator(){
        return employees.iterator(); 
    }

}

public class Test{
    public static void main(String[]agrs){
        // 建立行政部門
        XingZhengDept xingzheng = new XingZhengDept();
        // 建立技術部門
        JiShuDept jishu = new JiShuDept();
        // 列印行政部門資訊
        printEmp(xingzheng.createIterator());
        // 列印技術部門資訊
        printEmp(jishu.createIterator());
    }
    /**
      列印員工資訊
    **/
    public void printEmp(Iterator iterator){
       while(iterator.hasNext()){
            Employee e = (Employee)iterator.next();
            System.out.println("員工:"+e.getName());
            System.out.println("薪資:"+e.getSalary());    
       }
    }
}

按照如上改造,兩個部門被改造成了迭代器模式。那組合模式又是什麼樣的呢?????

/**
   情景如下:
   我們公司有三個大的部門
   1.營銷部
   2.技術部
   3.行政部 
   營銷部直屬一個經理,和兩個營銷部長。
   營銷部下轄營銷一部和營銷二部。
   接下來我們看如何設計。   
**/

//首先我們把部門和員工都抽象成公司成員的一部分
public abstract class Member{
    // 定義公有的方法新增員工/部門
    public void add(Member m){
        throw new Exception("未新增實現");
    }
    
    public Member getChild(int i){
        throw new Exception("未新增實現");
    }
    
    public String getName(){
        throw new Exception("未新增實現");
    }

    public double getSalary(){
        throw new Exception("未新增實現");
    }

    public void print(){
        throw new Exception("未新增實現");
    }
}

/**
    員工類
**/
public class Emp extends Member{
    // 名稱
    private String name;
    // 薪資
    private double salary;
    // 構造方法
    public Emp(String name,double salary){
        this.name = name;
        this.salary = salary;
    }
    
    // 重寫getName方法
    public String getName(){
        return name;
    }

    // 重寫getSalary方法
    public double getSalary(){
        return salary;
    }

    // 重寫print方法
    public void print(){
        System.out.println("名字:"+name);
        System.out.println("薪水:"+salary);
    }
}

/**
    部門類
**/

public class Dept extends Members{
    ArrayList members;
    String deptName;
    // 構造方法
    public Dept (String deptName){
        this.deptName = deptName;
    }
    
    // 重寫getChild方法
    public Member getChild(int i){
        return (Member)members.get(i);
    }
    // 重寫print方法
    public void print(){
        System.out.println("部門為:"+deptName);
        System.out.println("--------------------------------------");
    }
}

把部門和員工都放到一個門類下,這樣便利的時候只需要根據不同的種類去判斷就可以了。