您好,登錄后才能下訂單哦!
本文實(shí)例講述了Java使用訪問者模式解決公司層級(jí)結(jié)構(gòu)圖問題。分享給大家供大家參考,具體如下:
一. 模式定義
訪問者模式:是表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中各個(gè)元素的操作,它使用戶可以在不改變各元素類的前提下定義作用于這些元素的新操作。
二. 模式舉例
1 模式分析
我們借用公司層級(jí)結(jié)構(gòu)來說明這一模式。
2 訪問者模式靜態(tài)類圖
3 代碼示例
3.1 抽象員工一Staff
package com.demo.structure; import com.demo.visitor.IVisitor; /** * 抽象員工類 * * @author * */ public abstract class Staff { // 員工號(hào) protected String no; // 職工名字 protected String name; // 職位 protected String position; // 薪資 protected float salary; // 私有屬性 長(zhǎng)度字符串 private int length; // 構(gòu)造方法 public Staff(String no, String name, String position, float salary) { this.no = no; this.name = name; this.position = position; this.salary = salary; // 計(jì)算總字節(jié)長(zhǎng)度 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); // 接收訪問者對(duì)象 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 { // 存儲(chǔ)手下員工信息 private final ArrayList<Staff> arrayList = new ArrayList<Staff>(); // 構(gòu)造方法 public Manager(String no, String name, String position, float salary) { super(no, name, position, salary); } /** * 增加一個(gè)員工 */ @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; } // 接收訪問者對(duì)象 @Override public void accept(IVisitor visitor) { // 訪問自身 visitor.visit(this); // 遍歷list列表中的各個(gè)元素對(duì)象,接收訪問者對(duì)象 for (int i = 0; i < this.arrayList.size(); i++) { if (this.arrayList.get(i) == null) { continue; } // 接收訪問者對(duì)象 this.arrayList.get(i).accept(visitor); } } }
3.3 普通員工一Employees
package com.demo.structure; import com.demo.visitor.IVisitor; /** * 普通員工(真正干活的人) * * @author * */ public class Employees extends Staff { // 構(gòu)造方法 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; } // 接收訪問者對(duì)象 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 { /** * 訪問管理者對(duì)象 */ public void visit(Manager manager) { System.out.print("- 管理者:"); manager.printUserBaseInfo(); } /** * 訪問普通員工對(duì)象 */ public void visit(Employees employees) { System.out.print("- 一般員工:"); employees.printUserBaseInfo(); } }
3.6 創(chuàng)建統(tǒng)計(jì)員工薪資的訪問者接口一ISalaryVistor
package com.demo.visitor; /** * 計(jì)算薪資訪問者 * * @author * */ public interface ISalaryVisitor extends IVisitor { // 統(tǒng)計(jì)管理者薪資情況 public void printManagerTotalSalary(); // 統(tǒng)計(jì)一般員工薪資情況 public void printEmployeesTotalSalary(); // 統(tǒng)計(jì)所有員工薪資情況 public void printTotalSalary(); }
3.7 統(tǒng)計(jì)員工薪資訪問者實(shí)現(xiàn)一SalaryVistor
package com.demo.visitor; import com.demo.structure.Employees; import com.demo.structure.Manager; /** * 計(jì)算薪資訪問者具體實(shí)現(xiàn) * * @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(); } // 統(tǒng)計(jì)一般員工薪資情況 public void printEmployeesTotalSalary() { System.out.println("一般員工薪資總和:" + employeesSalary); } // 統(tǒng)計(jì)管理者薪資情況 public void printManagerTotalSalary() { System.out.println("管理者薪資總和:" + managerSalary); } // 統(tǒng)計(jì)所有員工薪資情況 public void printTotalSalary() { System.out.println("員工薪資總和:" + (managerSalary + employeesSalary)); } }
3.8 客戶端測(cè)試一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; /** * 主應(yīng)用程序 * * @author * */ public class Client { /** * @param args */ public static void main(String[] args) { // 公司CEO Staff boss = new Manager("1", "大老板", "CEO", 100000); /** * CEO手下有若干部門經(jīng)理 */ // 財(cái)務(wù)部經(jīng)理 Staff financeManager = new Manager("11", "張總", "財(cái)務(wù)部經(jīng)理", 60000); // 人事部經(jīng)理 Staff personnelManager = new Manager("12", "王總", "人事部經(jīng)理", 60000); // 技術(shù)部經(jīng)理 Staff technicalManager = new Manager("13", "陳總", "技術(shù)部經(jīng)理", 60000); /** * 技術(shù)部門還有助理和若干主管 */ // 技術(shù)部門助理 Staff deptAssistant = new Manager("1301", "王助理", "部門助理", 20000); // 技術(shù)部門主管1 Staff deptManager1 = new Manager("1302", "主管1", "技術(shù)主管", 30000); /** * 技術(shù)主管deptManager1 下面還有軟件工程師(最終干活的人) */ Staff softwareEngineer1 = new Employees("1302001", "張三", "軟件工程師", 5000); Staff softwareEngineer2 = new Employees("1302002", "李四", "軟件工程師", 5500); Staff softwareEngineer3 = new Employees("1302003", "王五", "軟件工程師", 4500); // 為技術(shù)主管1添加員工信息 deptManager1.add(softwareEngineer1); deptManager1.add(softwareEngineer2); deptManager1.add(softwareEngineer3); // 技術(shù)部門主管2 Staff deptManager2 = new Manager("1303", "主管2", "技術(shù)主管", 30000); // 為技術(shù)部經(jīng)理 添加:部門助理、技術(shù)主管1和技術(shù)主管2 technicalManager.add(deptAssistant); technicalManager.add(deptManager1); technicalManager.add(deptManager2); // 市場(chǎng)部經(jīng)理 Staff marketingManager = new Manager("14", "吳總", "市場(chǎng)部經(jīng)理", 60000); // 為CEO 添加:財(cái)務(wù)部經(jīng)理、人事部經(jīng)理、技術(shù)部經(jīng)理和市場(chǎng)部經(jīng)理 boss.add(financeManager); boss.add(personnelManager); boss.add(technicalManager); boss.add(marketingManager); // 打印CEO 信息 // boss.printUserBaseInfo(); // 打印CEO 手下員工信息 boss.accept(new PrintBaseInfoVisitor()); /** * 統(tǒng)計(jì)員工薪資情況 */ // 創(chuàng)建統(tǒng)計(jì)員工薪資訪問者 SalaryVisitor visitor = new SalaryVisitor(); // 讓大老板接受該訪問者 boss.accept(visitor); // 管理者薪資統(tǒng)計(jì)情況 visitor.printManagerTotalSalary(); // 一般員工薪資統(tǒng)計(jì)情況 visitor.printEmployeesTotalSalary(); // 所有員工薪資統(tǒng)計(jì)情況 visitor.printTotalSalary(); } }
4 運(yùn)行結(jié)果
- 管理者:-|1 大老板 CEO 100000.0
- 管理者:-|11 張總 財(cái)務(wù)部經(jīng)理 60000.0
- 管理者:-|12 王總 人事部經(jīng)理 60000.0
- 管理者:-|13 陳總 技術(shù)部經(jīng)理 60000.0
- 管理者:-|1301 王助理 部門助理 20000.0
- 管理者:-|1302 主管1 技術(shù)主管 30000.0
- 一般員工:-|1302001 張三 軟件工程師 5000.0
- 一般員工:-|1302002 李四 軟件工程師 5500.0
- 一般員工:-|1302003 王五 軟件工程師 4500.0
- 管理者:-|1303 主管2 技術(shù)主管 30000.0
- 管理者:-|14 吳總 市場(chǎng)部經(jīng)理 60000.0
管理者薪資總和:420000.0
一般員工薪資總和:15000.0
員工薪資總和:435000.0
三. 該模式設(shè)計(jì)原則
1 "開-閉"原則
2 單一職責(zé)原則
四. 使用場(chǎng)合
1 如果在一個(gè)對(duì)象結(jié)構(gòu)中包含很多不同類型的對(duì)象,它們有不同的接口,而想對(duì)這些不同對(duì)象實(shí)施一些依賴于具體類的操作。
2 需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同的并且不相關(guān)操作,而想避免讓這些操作與這些對(duì)象的類關(guān)聯(lián)起來。訪問者模式使得可以將相關(guān)操作集中起來,單獨(dú)定義在一個(gè)類中。
3 當(dāng)該對(duì)象結(jié)構(gòu)被很多應(yīng)用共享時(shí),用訪問者模式讓每個(gè)應(yīng)用僅包含需要用到的操作。
4 定義對(duì)象結(jié)構(gòu)的類很少改變,但經(jīng)常需要在此結(jié)構(gòu)中定義新的操作。
五. 訪問者模式靜態(tài)類圖
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。