本文實例講述了Java使用訪問者模式解決公司層級結構圖問題。分享給大家供大家參考,具體如下:
一. 模式定義
訪問者模式:是表示一個作用於某對象結構中各個元素的操作,它使用戶可以在不改變各元素類的前提下定義作用於這些元素的新操作。
二. 模式舉例
1 模式分析
我們藉用公司層級結構來說明這一模式。
2 訪問者模式靜態類圖
3 代碼示例
3.1 抽象員工一Staff
package com.demo.structure;import com.demo.visitor.IVisitor;/** * 抽象員工類* * @author * */public abstract class Staff { // 員工號protected String no; // 職工名字protected String name; // 職位protected String position; // 薪資protected float salary; // 私有屬性長度字符串private int length; // 構造方法public Staff(String no, String name, String position, float salary) { this.no = no; this.name = name; this.position = position; this.salary = salary; // 計算總字節長度this.length += (no == null || "".equals(no.trim())) ? 0 : no.getBytes().length; this.length += (name == null || "".equals(name.trim())) ? 0 : name .getBytes().length; this.length += (position == null || "".equals(position.trim())) ? 0 : position.getBytes().length; this.length += String.valueOf(salary).getBytes().length; } // 獲得用戶基本信息public void printUserBaseInfo() { System.out.println("-|" + this.no + " " + this.name + " " + this.position + " " + this.salary); } // 添加員工信息public abstract void add(Staff staff); // 刪除員工public abstract Staff remove(String no); // 接收訪問者對象public abstract void accept(IVisitor visitor); public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPosition() { return position; } public void setPosition(String position) { this.position = position; } public float getSalary() { return salary; } public void setSalary(float salary) { this.salary = salary; }}3.2 管理者一Manager
package com.demo.structure;import java.util.ArrayList;import com.demo.visitor.IVisitor;/** * 管理人員(手下有其他員工的人) * * @author * */public class Manager extends Staff { // 存儲手下員工信息private final ArrayList<Staff> arrayList = new ArrayList<Staff>(); // 構造方法public Manager(String no, String name, String position, float salary) { super(no, name, position, salary); } /** * 增加一個員工*/ @Override public void add(Staff staff) { this.arrayList.add(staff); } /** * 刪除員工信息*/ @Override public Staff remove(String no) { Staff staff = null; if (no != null && !"".equals(no.trim())) { for (int i = 0; i < this.arrayList.size(); i++) { if (this.arrayList.get(i) == null) { continue; } if (no.equals(this.arrayList.get(i).getNo())) { staff = this.arrayList.remove(i); break; } } } return staff; } // 接收訪問者對象@Override public void accept(IVisitor visitor) { // 訪問自身visitor.visit(this); // 遍歷list列表中的各個元素對象,接收訪問者對象for (int i = 0; i < this.arrayList.size(); i++) { if (this.arrayList.get(i) == null) { continue; } // 接收訪問者對象this.arrayList.get(i).accept(visitor); } }}3.3 普通員工一Employees
package com.demo.structure;import com.demo.visitor.IVisitor;/** * 普通員工(真正幹活的人) * * @author * */public class Employees extends Staff{ // 構造方法public Employees(String no, String name, String position, float salary) { super(no, name, position, salary); } /** * 添加員工信息*/ @Override public void add(Staff staff) { return; } /** * 刪除員工信息*/ @Override public Staff remove(String no) { // 直接返回null return null; } // 接收訪問者對象public void accept(IVisitor visitor) { visitor.visit(this); }}3.4 訪問者接口一IVisitor
package com.demo.visitor;import com.demo.structure.Employees;import com.demo.structure.Manager;/** * 訪問者接口* * @author * */public interface IVisitor { // 訪問管理者public void visit(Manager manager); // 訪問普通員工public void visit(Employees employees);}3.5 員工基本信息訪問者一PrintBaseInfoVistor
package com.demo.visitor;import com.demo.structure.Employees;import com.demo.structure.Manager;/** * 打印基本信息訪問者* * @author * */public class PrintBaseInfoVisitor implements IVisitor { /** * 訪問管理者對象*/ public void visit(Manager manager) { System.out.print("- 管理者:"); manager.printUserBaseInfo(); } /** * 訪問普通員工對象*/ public void visit(Employees employees) { System.out.print("- 一般員工:"); employees.printUserBaseInfo(); }}3.6 創建統計員工薪資的訪問者接口一ISalaryVistor
package com.demo.visitor;/** * 計算薪資訪問者* * @author * */public interface ISalaryVisitor extends IVisitor { // 統計管理者薪資情況public void printManagerTotalSalary(); // 統計一般員工薪資情況public void printEmployeesTotalSalary(); // 統計所有員工薪資情況public void printTotalSalary();}3.7 統計員工薪資訪問者實現一SalaryVistor
package com.demo.visitor;import com.demo.structure.Employees;import com.demo.structure.Manager;/** * 計算薪資訪問者俱體實現* * @author * */public class SalaryVisitor implements ISalaryVisitor { // 管理者薪資總和private float managerSalary; // 普通員工薪資總和private float employeesSalary; public SalaryVisitor() { managerSalary = 0; employeesSalary = 0; } // 訪問管理者public void visit(Manager manager) { managerSalary += manager.getSalary(); } // 訪問普通員工public void visit(Employees employees) { employeesSalary += employees.getSalary(); } // 統計一般員工薪資情況public void printEmployeesTotalSalary() { System.out.println("一般員工薪資總和:" + employeesSalary); } // 統計管理者薪資情況public void printManagerTotalSalary() { System.out.println("管理者薪資總和:" + managerSalary); } // 統計所有員工薪資情況public void printTotalSalary() { System.out.println("員工薪資總和:" + (managerSalary + employeesSalary)); }}3.8 客戶端測試一Client
package com.demo;import com.demo.structure.Employees;import com.demo.structure.Manager;import com.demo.structure.Staff;import com.demo.visitor.PrintBaseInfoVisitor;import com.demo.visitor.SalaryVisitor;/** * 主應用程序* * @author * */public class Client { /** * @param args */ public static void main(String[] args) { // 公司CEO Staff boss = new Manager("1", "大老闆", "CEO", 100000); /** * CEO手下有若干部門經理*/ // 財務部經理Staff financeManager = new Manager("11", "張總", "財務部經理", 60000); // 人事部經理Staff personnelManager = new Manager("12", "王總", "人事部經理", 60000); // 技術部經理Staff technicalManager = new Manager("13", "陳總", "技術部經理", 60000); /** * 技術部門還有助理和若干主管*/ // 技術部門助理Staff deptAssistant = new Manager("1301", "王助理", "部門助理", 20000); // 技術部門主管1 Staff deptManager1 = new Manager("1302", "主管1", "技術主管", 30000); /** * 技術主管deptManager1 下面還有軟件工程師(最終幹活的人) */ Staff softwareEngineer1 = new Employees("1302001", "張三", "軟件工程師", 5000); Staff softwareEngineer2 = new Employees("1302002", "李四", "軟件工程師", 5500); Staff softwareEngineer3 = new Employees("1302003", "王五", "軟件工程師", 4500); // 為技術主管1添加員工信息deptManager1.add(softwareEngineer1); deptManager1.add(softwareEngineer2); deptManager1.add(softwareEngineer3); // 技術部門主管2 Staff deptManager2 = new Manager("1303", "主管2", "技術主管", 30000); // 為技術部經理添加:部門助理、技術主管1和技術主管2 technicalManager.add(deptAssistant); technicalManager.add(deptManager1); technicalManager.add(deptManager2); // 市場部經理Staff marketingManager = new Manager("14", "吳總", "市場部經理", 60000); // 為CEO 添加:財務部經理、人事部經理、技術部經理和市場部經理boss.add(financeManager); boss.add(personnelManager); boss.add(technicalManager); boss.add(marketingManager); // 打印CEO 信息// boss.printUserBaseInfo(); // 打印CEO 手下員工信息boss.accept(new PrintBaseInfoVisitor()); /** * 統計員工薪資情況*/ // 創建統計員工薪資訪問者SalaryVisitor visitor = new SalaryVisitor(); // 讓大老闆接受該訪問者boss.accept(visitor); // 管理者薪資統計情況visitor.printManagerTotalSalary(); // 一般員工薪資統計情況visitor.printEmployeesTotalSalary(); // 所有員工薪資統計情況visitor.printTotalSalary(); }}4 運行結果
- 管理者:-|1 大老闆CEO 100000.0
- 管理者:-|11 張總財務部經理60000.0
- 管理者:-|12 王總人事部經理60000.0
- 管理者:-|13 陳總技術部經理60000.0
- 管理者:-|1301 王助理部門助理20000.0
- 管理者:-|1302 主管1 技術主管30000.0
- 一般員工:-|1302001 張三軟件工程師5000.0
- 一般員工:-|1302002 李四軟件工程師5500.0
- 一般員工:-|1302003 王五軟件工程師4500.0
- 管理者:-|1303 主管2 技術主管30000.0
- 管理者:-|14 吳總市場部經理60000.0
管理者薪資總和:420000.0
一般員工薪資總和:15000.0
員工薪資總和:435000.0
三. 該模式設計原則
1 "開-閉"原則
2 單一職責原則
四. 使用場合
1 如果在一個對象結構中包含很多不同類型的對象,它們有不同的接口,而想對這些不同對象實施一些依賴於具體類的操作。
2 需要對一個對象結構中的對象進行很多不同的並且不相關操作,而想避免讓這些操作與這些對象的類關聯起來。訪問者模式使得可以將相關操作集中起來,單獨定義在一個類中。
3 當該對象結構被很多應用共享時,用訪問者模式讓每個應用僅包含需要用到的操作。
4 定義對象結構的類很少改變,但經常需要在此結構中定義新的操作。
五. 訪問者模式靜態類圖
更多java相關內容感興趣的讀者可查看本站專題:《Java數據結構與算法教程》、《Java操作DOM節點技巧總結》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設計有所幫助。