รูปแบบการออกแบบ (Design pattern) คือชุดของบทสรุปจำแนกและจัดหมวดหมู่ของประสบการณ์การออกแบบโค้ดที่ใช้ซ้ำ ๆ กันซึ่งคนส่วนใหญ่รู้จัก
รูปแบบการออกแบบแบ่งออกเป็น 3 ประเภท รวมทั้งหมด 23 ประเภท ได้แก่
เขียนโดยอ้างอิงถึงบทความใน Hongyang, Novice Tutorials ฯลฯ โปรดแก้ไขฉันหากมีข้อผิดพลาดใด ๆ หากมีการละเมิดโปรดติดต่อฉันเพื่อลบมัน
1. รูปแบบการออกแบบ รูปแบบผู้สังเกตการณ์ (Observer Pattern) นำบริการสาธารณะของ WeChat เป็นตัวอย่าง
2. รูปแบบการออกแบบ ลวดลายโรงงาน (Factory Pattern) เริ่มต้นด้วยการขาย Roujiamo
3. รูปแบบการออกแบบ รูปแบบการออกแบบซิงเกิลตัน (Singleton Pattern) การวิเคราะห์ที่สมบูรณ์
4. รูปแบบการออกแบบ รูปแบบกลยุทธ์ (Strategy Pattern) ใช้เกมบทบาทเป็นพื้นหลัง
5.รูปแบบการออกแบบ รูปแบบอะแดปเตอร์ (Adapter Pattern) นำเครื่องชาร์จโทรศัพท์มือถือมาเป็นตัวอย่าง
6. Design Pattern Command Pattern เพื่อจัดการเครื่องใช้ไฟฟ้าภายในบ้านอัจฉริยะ
7. Design Pattern Decorator Pattern พาคุณกลับไปสู่โลกแห่งตำนาน
8. โหมดการออกแบบ โหมดรูปลักษณ์ (Facade Pattern) โหมดภาพยนตร์เพียงคลิกเดียว
9. Design Pattern Template Method Pattern แสดงวันของโปรแกรมเมอร์
10. รูปแบบการออกแบบ รูปแบบของรัฐ (State Pattern) เอาเครื่องหยอดเหรียญเป็นตัวอย่าง
11. Design Pattern Builder Pattern (Builder Pattern) ยกตัวอย่างการสร้างรถยนต์และการซื้อรถยนต์
12. Design Pattern Prototype Pattern (รูปแบบต้นแบบ) นำรูปทรงหลายแบบมาเป็นตัวอย่าง
13. รูปแบบการออกแบบ รูปแบบฟลายเวท (Flyweight Pattern) จะสุ่มได้หลายรูปทรงเป็นตัวอย่าง
14. Design Pattern Proxy Pattern (Proxy Pattern) รับภาพจากดิสก์เป็นตัวอย่าง
15. รูปแบบการออกแบบ ลายสะพาน (Bridge Pattern) วาดภาพวงกลมที่มีสีต่างกันเป็นตัวอย่าง
16. รูปแบบการออกแบบผสมผสานรูปแบบ (Composite Pattern) นำการสร้างและการพิมพ์ลำดับชั้นของพนักงานเป็นตัวอย่าง
17. รูปแบบการออกแบบ Iterator Pattern (Iterator Pattern) ใช้ตัววนซ้ำพิมพ์ชื่อเป็นตัวอย่าง
18. รูปแบบการออกแบบ รูปแบบผู้ไกล่เกลี่ย (Mediator Pattern) นำห้องสนทนาสาธารณะเป็นตัวอย่าง
19. Design Pattern Memento Pattern (รูปแบบของที่ระลึก) ใช้ของที่ระลึกเป็นตัวอย่าง
20. รูปแบบการออกแบบ รูปแบบล่าม (รูปแบบล่าม) นำการอธิบายประโยคเป็นตัวอย่าง
21. รูปแบบการออกแบบ Chain of Responsibility Pattern (รูปแบบห่วงโซ่ความรับผิดชอบ) นำบันทึกการพิมพ์ใน Android Studio เป็นตัวอย่าง
22. รูปแบบการออกแบบ รูปแบบผู้มาเยือน (Visitor Pattern) นำแสดงส่วนประกอบต่างๆ ของคอมพิวเตอร์เป็นตัวอย่าง
- ผู้สังเกตการณ์
- โรงงาน
- ซิงเกิลตัน
- กลยุทธ์
- อะแดปเตอร์
- สั่งการ
- มัณฑนากร
- ซุ้ม
- วิธีเทมเพลต
- สถานะ
- ช่างก่อสร้าง
- ต้นแบบ
- ฟลายเวท
- หนังสือมอบฉันทะ
- สะพาน
- คอมโพสิต
- ตัววนซ้ำ
- คนกลาง
- ของที่ระลึก
- ห่วงโซ่แห่งความรับผิดชอบ
- ผู้มาเยือน
กำหนดการขึ้นต่อกันแบบหนึ่งต่อกลุ่มระหว่างออบเจ็กต์ ดังนั้นเมื่อออบเจ็กต์เปลี่ยนแปลง การขึ้นต่อกันทั้งหมดจะได้รับแจ้งและอัปเดตโดยอัตโนมัติ
มีหลายที่ใน JDK หรือ Andorid ที่ใช้รูปแบบผู้สังเกตการณ์ เช่น XXXView.addXXXListenter แน่นอนว่า XXXView.setOnXXXListener ไม่จำเป็นต้องเป็นรูปแบบผู้สังเกตการณ์ เนื่องจากรูปแบบผู้สังเกตการณ์เป็นความสัมพันธ์แบบหนึ่งต่อกลุ่ม และสำหรับ setXXXLlistener เป็นคู่เดียว ความสัมพันธ์ระหว่าง 1 และ 1 ควรเรียกว่าการโทรกลับ
อินเทอร์เฟซพิเศษ: Subject.java;
/**
* 注册一个观察者
*/
public void registerObserver ( Observer observer );
/**
* 移除一个观察者
*/
public void removeObserver ( Observer observer );
/**
* 通知所有观察者
*/
public void notifyObservers ();
คลาสการใช้งานของบัญชีบริการ 3D: ObjectFor3D.java
@ Override
public void registerObserver ( Observer observer ) {
observers . add ( observer );
}
@ Override
public void removeObserver ( Observer observer ) {
int index = observers . indexOf ( observer );
if ( index >= 0 ) {
observers . remove ( index );
}
}
@ Override
public void notifyObservers () {
for ( Observer observer : observers ) {
observer . update ( msg );
}
}
/**
* 主题更新信息
*/
public void setMsg ( String msg ) {
this . msg = msg ;
notifyObservers ();
}
ผู้สังเกตการณ์ทุกคนจำเป็นต้องใช้อินเทอร์เฟซนี้: Observer.java
public ObserverUser1 ( Subject subject ) {
subject . registerObserver ( this );
}
@ Override
public void update ( String msg ) {
Log . e ( "-----ObserverUser1 " , "得到 3D 号码:" + msg + ", 我要记下来。" );
}
การทดสอบครั้งสุดท้าย: ObserverActivity.java
// 创建服务号
objectFor3D = new ObjectFor3D ();
// 创建两个订阅者
observerUser1 = new ObserverUser1 ( objectFor3D );
observerUser2 = new ObserverUser2 ( objectFor3D );
// 两个观察者,发送两条信息
objectFor3D . setMsg ( "201610121 的3D号为:127" );
objectFor3D . setMsg ( "20161022 的3D号为:000" );
เรามาแสดงรายการตระกูลของรูปแบบนี้โดยย่อ:
1. โหมดโรงงานแบบคงที่
2. โหมดโรงงานธรรมดา (ซื้อ Roujiamo ในร้านค้า)
public RoujiaMo creatRoujiaMo ( String type ) {
RoujiaMo roujiaMo = null ;
switch ( type ) {
case "Suan" :
roujiaMo = new ZSuanRoujiaMo ();
break ;
case "La" :
roujiaMo = new ZLaRoujiaMo ();
break ;
case "Tian" :
roujiaMo = new ZTianRoujiaMo ();
break ;
default : // 默认为酸肉夹馍
roujiaMo = new ZSuanRoujiaMo ();
break ;
}
return roujiaMo ;
}
3. รูปแบบวิธีการโรงงาน (เปิดสาขา)
จัดเตรียมวิธีการเชิงนามธรรมสำหรับการสร้าง Roujia MoStore: RoujiaMoStore.java
public abstract RoujiaMo sellRoujiaMo ( String type );
การใช้งานวิธีนามธรรมโดยเฉพาะ: XianRoujiaMoStore.java
สาขายังคงใช้โมเดลโรงงานแบบเรียบง่าย: XianSimpleRoujiaMoFactory.java
4. ลายโรงงานนามธรรม (ใช้วัตถุดิบอย่างเป็นทางการ)
/**
* 准备工作
*/
public void prepare ( RoujiaMoYLFactory roujiaMoYLFactory ) {
Meet meet = roujiaMoYLFactory . creatMeet ();
YuanLiao yuanLiao = roujiaMoYLFactory . creatYuanLiao ();
Log . e ( "---RoujiaMo:" , "使用官方的原料 ---" + name + ": 揉面-剁肉-完成准备工作 yuanLiao:" + meet + "yuanLiao:" + yuanLiao );
}
โหมดซิงเกิลตันมีไว้เพื่อหลีกเลี่ยงการสิ้นเปลืองทรัพยากรที่เกิดจากการสร้างหลายอินสแตนซ์เป็นหลัก และหลายอินสแตนซ์อาจนำไปสู่ผลลัพธ์ที่ไม่ถูกต้องเนื่องจากการเรียกหลายครั้ง ทำให้มั่นใจได้ว่ามีเพียงอินสแตนซ์เดียวในแอปพลิเคชันทั้งหมด
คำจำกัดความ: เพียงสามขั้นตอนเท่านั้นที่จำเป็นเพื่อให้แน่ใจว่าวัตถุมีเอกลักษณ์เฉพาะตัว
เปรียบเทียบคำจำกัดความ:
สไตล์ฮันกรีฮัน [มี]: SingletonEHan.java
ประกอบด้วยสไตล์ Han ขี้เกียจ [แนะนำการล็อคการยืนยันสองครั้ง]: SingletonLanHan.java
private SingletonLanHan () {}
private static SingletonLanHan singletonLanHanFour ;
public static SingletonLanHan getSingletonLanHanFour () {
if ( singletonLanHanFour == null ) {
synchronized ( SingletonLanHan . class ) {
if ( singletonLanHanFour == null ) {
singletonLanHanFour = new SingletonLanHan ();
}
}
}
return singletonLanHanFour ;
}
รูปแบบกลยุทธ์: กำหนดกลุ่มอัลกอริธึมและสรุปแยกกันเพื่อให้สามารถใช้แทนกันได้ รูปแบบนี้ช่วยให้การเปลี่ยนแปลงอัลกอริธึมเป็นอิสระจากลูกค้าที่ใช้อัลกอริธึม
RoleA roleA = new RoleA ( "---A" );
roleA . setiDisplayBehavior ( new DisplayYZ ())
. setiAttackBehavior ( new AttackXL ())
. setiDefendBehavior ( new DefendTMS ())
. setiRunBehavior ( new RunJCTQ ());
roleA . display (); // 样子
roleA . attack (); // 攻击
roleA . run (); // 逃跑
roleA . defend (); // 防御
คำจำกัดความ: แปลงอินเทอร์เฟซของคลาสให้เป็นอินเทอร์เฟซอื่นที่ไคลเอ็นต์คาดหวัง อะแด็ปเตอร์อนุญาตให้คลาสที่มีอินเทอร์เฟซที่เข้ากันไม่ได้สามารถทำงานร่วมกันได้ คำจำกัดความนี้ใช้ได้ โดยบอกว่าฟังก์ชันของอะแดปเตอร์คือการแปลงอินเทอร์เฟซหนึ่งเป็นอินเทอร์เฟซอื่น
ยกตัวอย่างที่ชาร์จ: โดยทั่วไปที่ชาร์จโทรศัพท์มือถือจะอยู่ที่ประมาณ 5V แรงดันไฟฟ้ากระแสสลับในครัวเรือนของเราในจีนคือ 220V ดังนั้นการชาร์จโทรศัพท์มือถือจึงต้องใช้อะแดปเตอร์ (ตัวลดแรงดันไฟฟ้า)
โทรศัพท์มือถือ: Mobile.java
โทรศัพท์ใช้อินเทอร์เฟซที่ให้แรงดันไฟฟ้า 5V: V5Power.java
ที่เรามีคือไฟบ้าน 220V AC: V220Power.java
อะแดปเตอร์เพื่อทำหน้าที่แปลง 220V เป็น 5V ให้สมบูรณ์ : V5PowerAdapter.java
การทดสอบครั้งสุดท้าย: ชาร์จโทรศัพท์:
Mobile mobile = new Mobile ();
V5Power v5Power = new V5PowerAdapter ( new V200Power ());
mobile . inputPower ( v5Power );
คำจำกัดความ: สรุป "คำขอ" ลงในออบเจ็กต์เพื่อให้ออบเจ็กต์อื่นๆ สามารถกำหนดพารามิเตอร์โดยใช้คำขอ คิว หรือบันทึกที่แตกต่างกัน โหมดคำสั่งยังรองรับการดำเนินการที่เลิกทำได้ (การทำให้เข้าใจง่าย: สรุปคำขอลงในออบเจ็กต์และแยกผู้ร้องขอการดำเนินการและผู้ดำเนินการการดำเนินการ)
QuickCommand quickCloseCommand = new QuickCommand ( new Command []{ new LightOffCommand ( light ), new ComputerOffCommand ( computer ), new DoorCloseCommand ( door )});
controlPanel . setCommands ( 6 , quickOpenCommand );
controlPanel . keyPressed ( 6 );
controlPanel . setCommands ( 0 , new DoorOpenCommand ( door )); // 开门
controlPanel . keyPressed ( 0 );
รูปแบบมัณฑนากร: เพื่อขยายฟังก์ชันการทำงาน ผู้ตกแต่งจึงมอบทางเลือกที่ยืดหยุ่นมากขึ้นในการบูรณาการ โดยแนบความรับผิดชอบกับวัตถุแบบไดนามิก
มาอธิบายสั้นๆ ว่ารูปแบบการตกแต่งเข้ามามีบทบาทอย่างไร เมื่อเราออกแบบคลาส เราจำเป็นต้องเพิ่มฟังก์ชันเสริมบางอย่างให้กับคลาสนี้ และเราไม่ต้องการเปลี่ยนโค้ดของคลาสนี้ นี่คือตอนที่รูปแบบการตกแต่งเข้ามา เล่น. ถึงเวลาแล้ว. สิ่งนี้ยังสะท้อนถึง หลักการ: คลาสควรเปิดสำหรับส่วนขยายและปิดสำหรับการแก้ไข
ข้อกำหนด: ออกแบบระบบอุปกรณ์ของเกม ข้อกำหนดพื้นฐานคือเพื่อให้สามารถคำนวณพลังโจมตีและคำอธิบายของอุปกรณ์แต่ละชิ้นได้หลังจากฝังด้วยอัญมณีต่างๆ:
1. อุปกรณ์ระดับสุดยอด: IEquip.java
2. ระดับการใช้งานของแต่ละอุปกรณ์:
3. การตกแต่งระดับสุดยอด (การตกแต่งยังเป็นของอุปกรณ์): IEquipDecorator.java
4. ระดับการใช้งานของการตกแต่ง:
5. การทดสอบครั้งสุดท้าย: คำนวณพลังโจมตีและดูคำอธิบาย:
Log . e ( "---" , "一个镶嵌2颗红宝石,1颗蓝宝石的靴子: " );
IEquip iEquip = new RedGemDecorator ( new RedGemDecorator ( new BlueGemDecorator ( new ShoeEquip ())));
Log . e ( "---" , "攻击力:" + iEquip . caculateAttack ());
Log . e ( "---" , "描述语:" + iEquip . description ());
คำจำกัดความ: จัดเตรียมอินเทอร์เฟซแบบรวมสำหรับการเข้าถึงกลุ่มอินเทอร์เฟซในระบบย่อย ลักษณะที่ปรากฏจะกำหนดอินเทอร์เฟซระดับสูงเพื่อทำให้ระบบย่อยใช้งานง่ายขึ้น ที่จริงแล้ว เพื่อความสะดวกของลูกค้า กลุ่มของการดำเนินการจึงถูกสรุปไว้เป็นวิธีการ
ความต้องการ: ฉันชอบดูภาพยนตร์ ดังนั้นฉันจึงซื้อโปรเจ็กเตอร์ คอมพิวเตอร์ เครื่องเสียง ออกแบบระบบไฟในห้อง และซื้อเครื่องทำป๊อปคอร์น จากนั้นเมื่อฉันต้องการชมภาพยนตร์ ฉันต้องดูด้วยคลิกเดียวและปิดเครื่องด้วยคลิกเดียว .
สวิตช์และการทำงานอื่นๆ สำหรับแต่ละคลาสอุปกรณ์:
เช่น เครื่องทำป๊อปคอร์น: PopcornPopper.java
คลาสภาพยนตร์: HomeTheaterFacade.java
/**
* 一键观影
*/
public void watchMovie () {
computer . on ();
light . down ();
popcornPopper . on ();
popcornPopper . makePopcorn ();
projector . on ();
projector . open ();
player . on ();
player . make3DListener ();
}
การทดสอบครั้งสุดท้าย: การชมภาพยนตร์ด้วยคลิกเดียว:
new HomeTheaterFacade ( computer , light , player , popcornPopper , projector ). watchMovie ();
คำจำกัดความ: กำหนดโครงร่างของอัลกอริทึมและเลื่อนบางขั้นตอนไปยังคลาสย่อย วิธีการเทมเพลตอนุญาตให้คลาสย่อยกำหนดขั้นตอนของอัลกอริทึมใหม่โดยไม่ต้องเปลี่ยนโครงสร้างอัลกอริทึม
ข้อกำหนด: อธิบายโดยย่อ: บริษัทของเรามีโปรแกรมเมอร์ ผู้ทดสอบ ทรัพยากรบุคคล ผู้จัดการโครงการ ฯลฯ โหมดวิธีการเทมเพลตจะใช้ด้านล่างเพื่อบันทึกสถานะการทำงานของบุคลากรทั้งหมด
บทบาทสามประเภทในรูปแบบวิธีการเทมเพลต
1. วิธีการคอนกรีต
2. วิธีการเชิงนามธรรม
3. วิธีขอเกี่ยว
ซูเปอร์คลาสของผู้ปฏิบัติงาน: Worker.java
// 具体方法
public final void workOneDay () {
Log . e ( "workOneDay" , "-----------------work start----------------" );
enterCompany ();
work ();
exitCompany ();
Log . e ( "workOneDay" , "-----------------work end----------------" );
}
// 工作 抽象方法
public abstract void work ();
// 钩子方法
public boolean isNeedPrintDate () {
return false ;
}
private void exitCompany () {
if ( isNeedPrintDate ()) {
Log . e ( "exitCompany" , "---" + new Date (). toLocaleString () + "--->" );
}
Log . e ( "exitCompany" , name + "---离开公司" );
}
คลาสการใช้งานโปรแกรมเมอร์ (สามารถทราบเวลาได้): ITWorker.java
/**
* 重写父类的此方法,使可以查看离开公司时间
*/
@ Override
public boolean isNeedPrintDate () {
return true ;
}
การทดสอบครั้งสุดท้าย:
ดูว่าทุกคนทำงานอย่างไร:
QAWorker qaWorker = new QAWorker ( "测试人员" );
qaWorker ();
HRWorker hrWorker = new HRWorker ( "莉莉姐" );
hrWorker . workOneDay ();
...
ตรวจสอบว่าโปรแกรมเมอร์ออกจากบริษัทเมื่อใด:
ITWorker itWorker = new ITWorker ( "jingbin" );
itWorker . workOneDay ();
คำจำกัดความ: อนุญาตให้วัตถุเปลี่ยนพฤติกรรมเมื่อสถานะภายในเปลี่ยนแปลง ทำให้วัตถุปรากฏราวกับว่าได้แก้ไขคลาสของมัน
คำจำกัดความเริ่มคลุมเครืออีกครั้ง ลองคิดดูว่าเมื่อสถานะภายในของวัตถุเปลี่ยนไป พฤติกรรมของวัตถุก็จะเปลี่ยนไปตามการเปลี่ยนแปลงของสถานะ
ข้อกำหนด: ยกตัวอย่างตู้จำหน่ายสินค้าอัตโนมัติ (มีสถานะเช่น หยอดเหรียญและไม่หยอดเหรียญ และวิธีการหยอดเหรียญและคืนเหรียญ)
การใช้งานเครื่องจำหน่ายสินค้าอัตโนมัติเบื้องต้นที่ต้องปรับปรุง: VendingMachine.java
ตู้จำหน่ายสินค้าอัตโนมัติที่ได้รับการปรับปรุง (ปรับเปลี่ยนได้มากขึ้น): VendingMachineBetter.java
// 放钱
public void insertMoney () {
currentState . insertMoney ();
}
// 退钱
public void backMoney () {
currentState . backMoney ();
}
// 转动曲柄
public void turnCrank () {
currentState . turnCrank ();
if ( currentState == soldState || currentState == winnerState ) {
currentState . dispense (); //两种情况会出货
}
}
// 出商品
public void dispense () {
Log . e ( "VendingMachineBetter" , "---发出一件商品" );
if ( count > 0 ) {
count --;
}
}
// 设置对应状态
public void setState ( State state ) {
this . currentState = state ;
}
อินเทอร์เฟซสถานะ: State.java
คลาสการใช้งานอินเทอร์เฟซที่สอดคล้องกับสถานะ:
ปรับปรุงการทดสอบเครื่องหยอดเหรียญ:
// 初始化售货机,且里面有3个商品
VendingMachineBetter machineBetter = new VendingMachineBetter ( 3 );
machineBetter . insertMoney ();
machineBetter . turnCrank ();
โหมดการก่อสร้างเป็นโหมดการสร้างวัตถุ โหมดการก่อสร้างสามารถแยกการนำเสนอภายในของผลิตภัณฑ์ออกจากกระบวนการผลิตของผลิตภัณฑ์ เพื่อให้กระบวนการก่อสร้างสามารถสร้างออบเจ็กต์ผลิตภัณฑ์ที่มีการนำเสนอภายในที่แตกต่างกันได้
ข้อกำหนด: ผู้ใช้ไปที่ร้านขายรถยนต์เพื่อซื้อรถยนต์
การวิเคราะห์: ร้านขายรถยนต์แยกรถยนต์ที่เกี่ยวข้องตามความต้องการของผู้ใช้แต่ละคน
ซูเปอร์คลาสตัวสร้าง: ตัวสร้าง
public abstract class Builder {
public abstract void setPart ( String name , String type );
public abstract Product getProduct ();
}
คลาสการใช้งานที่สอดคล้องกันของ Builder: ConcreteBuilder
public class ConcreteBuilder extends Builder {
private Product product = new Product ();
@ Override
public void setPart ( String name , String type ) {
product . setName ( name );
product . setType ( type );
}
@ Override
public Product getProduct () {
return product ;
}
}
ผู้จัดการร้านมารับรถ:
// 店长
Director director = new Director ();
// 得到宝马汽车,内部实现提取宝马汽车的详情操作
Product product = director . getBProduct ();
// 展示汽车信息
product . showProduct ();
รูปแบบต้นแบบใช้เพื่อสร้างวัตถุซ้ำๆ ขณะเดียวกันก็รับประกันประสิทธิภาพ รูปแบบการออกแบบประเภทนี้เป็นรูปแบบการสร้างสรรค์ ซึ่งเป็นแนวทางที่เหมาะสมที่สุดในการสร้างวัตถุ
รูปแบบนี้ใช้อินเทอร์เฟซต้นแบบที่ใช้ในการสร้างโคลนของออบเจ็กต์ปัจจุบัน โหมดนี้ใช้เมื่อต้นทุนในการสร้างวัตถุโดยตรงค่อนข้างสูง ตัวอย่างเช่น จำเป็นต้องสร้างออบเจ็กต์หลังจากการดำเนินการฐานข้อมูลที่มีราคาแพง เราสามารถแคชออบเจ็กต์ ส่งคืนโคลนของออบเจ็กต์ในคำขอถัดไป และอัปเดตฐานข้อมูลเมื่อจำเป็นเพื่อลดการเรียกฐานข้อมูล
การรับหลายรูปร่างเป็นตัวอย่าง มีสี่ขั้นตอน:
1. สร้างคลาสนามธรรมที่ใช้อินเทอร์เฟซ Cloneable รูปร่าง (นำไปใช้แบบโคลนได้)
public abstract class Shape implements Cloneable {
private String id ;
protected String type ;
public abstract void draw ();
public String getId () {
return id ;
}
public void setId ( String id ) {
this . id = id ;
}
@ Override
public Object clone () {
Object object = null ;
try {
object = super . clone ();
} catch ( CloneNotSupportedException e ) {
Log . e ( "--" , e . getMessage ());
}
return object ;
}
}
2. สร้างคลาสเอนทิตีที่ขยายคลาสนามธรรมข้างต้น วงกลม สี่เหลี่ยม สี่เหลี่ยม
public class Circle extends Shape {
public Circle () {
type = "Circle" ;
}
@ Override
public void draw () {
Log . e ( "---" , "Inside Circle::draw() method." );
}
}
3. สร้างคลาสเพื่อรับคลาสเอนทิตีจากฐานข้อมูลและจัดเก็บไว้ใน Hashtable เชปแคช
public class ShapeCache {
private static Hashtable < String , Shape > shapeMap = new Hashtable < String , Shape >();
public static Shape getShape ( String shapeId ) {
Shape shapeCache = shapeMap . get ( shapeId );
return ( Shape ) shapeCache . clone ();
}
// 对每种形状都运行数据库查询,并创建该形状
// shapeMap.put(shapeKey, shape);
// 例如,我们要添加三种形状
public static void loadCache () {
Circle circle = new Circle ();
circle . setId ( "1" );
shapeMap . put ( circle . getId (), circle );
Rectangle rectangle = new Rectangle ();
rectangle . setId ( "2" );
shapeMap . put ( rectangle . getId (), rectangle );
Square square = new Square ();
square . setId ( "3" );
shapeMap . put ( square . getId (), square );
}
}
4. ใช้คลาส ShapeCache เพื่อรับโคลนของรูปร่างที่จัดเก็บไว้ใน Hashtable
// 使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。
ShapeCache . loadCache ();
Shape shapeCache1 = ShapeCache . getShape ( "1" );
Shape shapeCache2 = ShapeCache . getShape ( "2" );
Shape shapeCache3 = ShapeCache . getShape ( "3" );
ส่วนใหญ่ใช้เพื่อลดจำนวนวัตถุที่สร้างขึ้นเพื่อลดการใช้หน่วยความจำและปรับปรุงประสิทธิภาพ รูปแบบการออกแบบประเภทนี้เป็นรูปแบบโครงสร้างซึ่งให้วิธีการลดจำนวนวัตถุและปรับปรุงโครงสร้างของวัตถุที่แอปพลิเคชันต้องการ
รูปแบบฟลายเวทจะพยายามนำวัตถุที่มีอยู่ประเภทเดียวกันกลับมาใช้ใหม่ หรือสร้างวัตถุใหม่หากไม่พบวัตถุที่ตรงกัน เราจะสาธิตรูปแบบนี้โดยการสร้างวัตถุ 5 ชิ้นที่วาดวงกลม 20 วงในตำแหน่งต่างๆ เนื่องจากมีเพียง 5 สีให้เลือก คุณสมบัติสีจึงถูกใช้เพื่อตรวจสอบวัตถุวงกลมที่มีอยู่
จากการสุ่มรับหลายรูปร่างเป็นตัวอย่าง มีสี่ขั้นตอน:
1. สร้างอินเทอร์เฟซ
public interface Shape {
void draw ();
}
2. สร้างคลาสเอนทิตีที่ใช้อินเทอร์เฟซ
public class Circle implements Shape {
private String color ;
private int x ;
private int y ;
private int radius ;
public Circle ( String color ) {
this . color = color ;
}
public void setX ( int x ) {
this . x = x ;
}
public void setY ( int y ) {
this . y = y ;
}
public void setRadius ( int radius ) {
this . radius = radius ;
}
@ Override
public void draw () {
Log . e ( "---" , "Circle: Draw() [Color : " + color
+ ", x : " + x + ", y :" + y + ", radius :" + radius );
}
}
3. สร้างโรงงานเพื่อสร้างออบเจ็กต์ของคลาสเอนทิตีตามข้อมูลที่ให้มา
public class ShapeFactory {
private static final HashMap < String , Shape > circleMap = new HashMap < String , Shape >();
public static Shape getShape ( String color ) {
Shape shape = circleMap . get ( color );
if ( shape == null ) {
shape = new Circle ( color );
circleMap . put ( color , shape );
Log . e ( "getShape" , "Creating circle of color : " + color );
}
return shape ;
}
}
4. ใช้โรงงานนี้เพื่อรับออบเจ็กต์ของคลาสเอนทิตีโดยส่งข้อมูลสี
for ( int i = 0 ; i < 20 ; i ++) {
Circle circle = ( Circle ) ShapeFactory . getShape ( getRandomColor ());
circle . setX ( getRandomX ());
circle . setY ( getRandomY ());
circle . setRadius ( 100 );
circle . draw ();
}
คลาสหนึ่งแสดงถึงการทำงานของคลาสอื่น ในรูปแบบพร็อกซี เราสร้างออบเจ็กต์ด้วยออบเจ็กต์ที่มีอยู่เพื่อจัดเตรียมอินเทอร์เฟซการทำงานให้กับโลกภายนอก เข้าใจได้ว่าหากไม่มีวัตถุดังกล่าวในหน่วยความจำ มันก็จะถูกสร้างขึ้น และถ้ามี วัตถุนั้นก็จะถูกส่งกลับโดยตรง
การรับรูปภาพจากดิสก์เป็นตัวอย่าง มีทั้งหมด 3 ขั้นตอน:
1. สร้างอินเทอร์เฟซ
public interface Image {
void display ();
}
2. สร้างคลาสเอนทิตี RealImage ที่ใช้อินเทอร์เฟซ คลาสพร็อกซีที่สอดคล้องกัน: ProxyImage
public class RealImage implements Image {
private String fileName ;
public RealImage ( String fileName ) {
this . fileName = fileName ;
loadFromDisk ( fileName );
}
private void loadFromDisk ( String fileName ) {
Log . e ( "RealImage" , "loading " + fileName );
}
@ Override
public void display () {
Log . e ( "RealImage" , "Displaying " + fileName );
}
}
public class ProxyImage implements Image {
private String fileName ;
private RealImage realImage ;
public ProxyImage ( String fileName ) {
this . fileName = fileName ;
}
@ Override
public void display () {
if ( realImage == null ) {
realImage = new RealImage ( fileName );
}
realImage . display ();
}
}
3. เมื่อได้รับการร้องขอ ให้ใช้ ProxyImage เพื่อรับอ็อบเจ็กต์ของคลาส RealImage
Image image = new ProxyImage ( "test_10mb.png" );
// 第一次是new的,图像从磁盘加载
image . display ();
// 第二次取缓存,图像不需要从磁盘加载
image . display ();
Bridge ใช้เพื่อแยกนามธรรมและการนำไปใช้ เพื่อให้ทั้งสองสามารถเปลี่ยนแปลงได้อย่างอิสระ รูปแบบการออกแบบประเภทนี้เป็นรูปแบบโครงสร้าง ซึ่งจะแยกนามธรรมและการนำไปใช้ออกโดยจัดให้มีโครงสร้างที่เชื่อมโยงระหว่างสิ่งเหล่านั้น
ยกตัวอย่างการวาดวงกลมที่มีสีต่างกัน การดำเนินการแบ่งออกเป็น 5 ขั้นตอน:
1. สร้างอินเทอร์เฟซการใช้งานบริดจ์
public interface DrawAPI {
void drawCircle ( int radius , int x , int y );
}
2. สร้างคลาสการใช้งานเอนทิตีบริดจ์ที่ใช้อินเทอร์เฟซ DrawAPI วงกลมสีแดง, วงกลมสีเขียว
public class RedCircle implements DrawAPI {
@ Override
public void drawCircle ( int radius , int x , int y ) {
Log . e ( "---" , "Drawing Circle[ color: red, radius: "
+ radius + ", x: " + x + ", " + y + "]" );
}
}
3. ใช้อินเทอร์เฟซ DrawAPI เพื่อสร้างรูปร่างคลาสนามธรรม
public abstract class Shape {
protected DrawAPI drawAPI ;
protected Shape ( DrawAPI drawAPI ) {
this . drawAPI = drawAPI ;
}
public abstract void draw ();
}
4. สร้างคลาสเอนทิตีที่ใช้อินเทอร์เฟซ Shape
public class Circle extends Shape {
private int x , y , radius ;
protected Circle ( int x , int y , int radius , DrawAPI drawAPI ) {
super ( drawAPI );
this . x = x ;
this . y = y ;
this . radius = radius ;
}
@ Override
public void draw () {
drawAPI . drawCircle ( radius , x , y );
}
}
5. ใช้คลาส Shape และ DrawAPI เพื่อวาดวงกลมที่มีสีต่างกัน
// 画红圆
Circle circle = new Circle ( 10 , 10 , 100 , new RedCircle ()); s
circle . draw ();
// 画绿圆
Circle circle2 = new Circle ( 20 , 20 , 100 , new GreenCircle ());
circle2 . draw ();
เรียกอีกอย่างว่ารูปแบบบางส่วนทั้งหมด ซึ่งใช้เพื่อถือว่ากลุ่มของวัตถุที่คล้ายกันเป็นวัตถุเดียว โหมดการจัดองค์ประกอบจะรวมวัตถุตามโครงสร้างแบบต้นไม้ ซึ่งใช้เพื่อแสดงลำดับชั้นบางส่วนและทั้งหมด รูปแบบการออกแบบประเภทนี้เป็นรูปแบบโครงสร้างซึ่งสร้างโครงสร้างต้นไม้ของกลุ่มวัตถุ
ยกตัวอย่างการสร้างและพิมพ์ลำดับชั้นของพนักงาน ตัวอย่างหน่วยที่เล็กที่สุด:
1. สร้างคลาส Employee พร้อมรายการออบเจ็กต์ Employee
public class Employee {
private String name ;
// 部门
private String dept ;
// 工资
private int salary ;
// 员工 list
private List < Employee > subordinates ;
public Employee ( String name , String dept , int salary ) {
this . name = name ;
this . dept = dept ;
this . salary = salary ;
this . subordinates = new ArrayList < Employee >();
}
public void add ( Employee e ) {
subordinates . add ( e );
}
public void remove ( Employee e ) {
subordinates . remove ( e );
}
public List < Employee > getSubordinates () {
return subordinates ;
}
@ Override
public String toString () {
return "Employee{" +
"name='" + name + ''' +
", dept='" + dept + ''' +
", salary=" + salary +
", subordinates=" + subordinates +
'}' ;
}
}
2. ใช้คลาส Employee เพื่อสร้างและพิมพ์ลำดับชั้นของพนักงาน
final Employee ceo = new Employee ( "John" , "CEO" , 30000 );
Employee headSales = new Employee ( "Robert" , "Head sales" , 20000 );
Employee headMarketing = new Employee ( "Michel" , "Head Marketing" , 20000 );
Employee clerk1 = new Employee ( "Laura" , "Marketing" , 10000 );
Employee clerk2 = new Employee ( "Bob" , "Marketing" , 10000 );
Employee salesExecutive1 = new Employee ( "Richard" , "Sales" , 10000 );
Employee salesExecutive2 = new Employee ( "Rob" , "Sales" , 10000 );
ceo . add ( headSales );
ceo . add ( headMarketing );
headSales . add ( salesExecutive1 );
headSales . add ( salesExecutive2 );
headMarketing . add ( clerk1 );
headMarketing . add ( clerk2 );
Log . e ( "---" , ceo . toString ());
// 打印
/*
* Employee{name='John', dept='CEO', salary=30000,
* subordinates=[Employee{name='Robert', dept='Head sales', salary=20000,
* subordinates=[
* Employee{name='Richard', dept='Sales', salary=10000, subordinates=[]},
* Employee{name='Rob', dept='Sales', salary=10000, subordinates=[]}]},
* Employee{name='Michel', dept='Head Marketing', salary=20000,
* subordinates=[Employee{name='Laura', dept='Marketing', salary=10000, subordinates=[]},
* Employee{name='Bob', dept='Marketing', salary=10000, subordinates=[]}]}]}
*/
รูปแบบการออกแบบที่พบบ่อยมากในสภาพแวดล้อมการเขียนโปรแกรม Java และ .Net รูปแบบนี้ใช้เพื่อเข้าถึงองค์ประกอบของออบเจ็กต์คอลเลกชันตามลำดับโดยไม่ทราบถึงการแสดงพื้นฐานของออบเจ็กต์คอลเลกชัน รูปแบบตัววนซ้ำเป็นรูปแบบพฤติกรรม
การใช้ตัววนซ้ำเพื่อพิมพ์ชื่อเป็นตัวอย่าง มีทั้งหมดสามขั้นตอน:
1. สร้างอินเทอร์เฟซ:
public interface Iterator {
public boolean hasNext ();
public Object next ();
}
public interface Container {
public Iterator getIterator ();
}
2. สร้างคลาสเอนทิตีที่ใช้อินเทอร์เฟซคอนเทนเนอร์ คลาสนี้มี NameIterator คลาสภายในที่ใช้อินเทอร์เฟซ Iterator
public class NameRepository implements Container {
private String names [] = { "John" , "jingbin" , "youlookwhat" , "lookthis" };
@ Override
public Iterator getIterator () {
return new NameIterator ();
}
private class NameIterator implements Iterator {
int index ;
@ Override
public boolean hasNext () {
if ( index < names . length ) {
return true ;
}
return false ;
}
@ Override
public Object next () {
if ( hasNext ()) {
return names [ index ++];
}
return null ;
}
}
}
3. ใช้ NameRepository เพื่อรับตัววนซ้ำและพิมพ์ชื่อ
NameRepository nameRepository = new NameRepository ();
for ( Iterator iterator = nameRepository . getIterator (); iterator . hasNext (); ) {
String name = ( String ) iterator . next ();
Log . e ( "---" , name );
/*
* /---: John
* /---: jingbin
* /---: youlookwhat
* /---: lookthis
*/
}
ใช้เพื่อลดความซับซ้อนของการสื่อสารระหว่างหลายวัตถุและคลาส รูปแบบนี้จัดให้มีคลาสตัวกลางที่โดยทั่วไปจะจัดการการสื่อสารระหว่างคลาสต่างๆ และรองรับการเชื่อมต่อแบบหลวมๆ ทำให้ง่ายต่อการบำรุงรักษาโค้ด โมเดลผู้ไกล่เกลี่ยเป็นรูปแบบพฤติกรรม
ยกตัวอย่างห้องสนทนาสาธารณะ ขั้นตอนตัวอย่างขั้นต่ำของหน่วยคือ:
1. สร้างคลาสตัวกลาง
public class CharRoom {
public static void showMessage ( User user , String message ) {
Log . e ( "---" , new Date (). toString ()
+ " [" + user . getName () + "] : " + message );
}
}
2. สร้างคลาสผู้ใช้
public class User {
private String name ;
public User ( String name ) {
this . name = name ;
}
public String getName () {
return name ;
}
public void setName ( String name ) {
this . name = name ;
}
public void sendMessage ( String message ) {
// 使用中介类
CharRoom . showMessage ( this , message );
}
}
3. ใช้วัตถุผู้ใช้เพื่อแสดงการสื่อสารระหว่างกัน
User jingbin = new User ( "jingbin" );
jingbin . sendMessage ( "Hi~ youlookwhat!" );
//---: Sun Feb 02 08:11:47 GMT+00:00 2020 [jingbin] : Hi~ youlookwhat!
User jingbin = new User ( "youlookwhat" );
jingbin . sendMessage ( "Hi~ jingbin!" );
//---: Sun Feb 02 08:11:49 GMT+00:00 2020 [youlookwhat] : Hi~ jingbin!
บันทึกสถานะของออบเจ็กต์เพื่อให้สามารถกู้คืนได้ในเวลาที่เหมาะสม โหมดบันทึกเป็นโหมดพฤติกรรม
การใช้บันทึกช่วยจำเป็นตัวอย่าง ขั้นตอนขั้นต่ำของหน่วยคือ:
1. สร้างคลาส Memento
public class Memento {
private String state ;
public Memento ( String state ) {
this . state = state ;
}
public String getState () {
return state ;
}
public void setState ( String state ) {
this . state = state ;
}
}
2. สร้างคลาส Originator
public class Originator {
private String state ;
public String getState () {
return state ;
}
public void setState ( String state ) {
this . state = state ;
}
public Memento setSateToMemento () {
return new Memento ( state );
}
public String getStateFromMemento ( Memento memento ) {
return memento . getState ();
}
}
3. สร้างคลาส CareTaker
public class CareTaker {
private List < Memento > mementoList = new ArrayList < Memento >();
public void add ( Memento memento ) {
mementoList . add ( memento );
}
public Memento get ( int index ) {
return mementoList . get ( index );
}
}
4. ใช้วัตถุ CareTaker และ Originator
// 管理者
CareTaker careTaker = new CareTaker ();
Originator originator = new Originator ();
originator . setState ( "State #1" );
originator . setState ( "State #2" );
// 保存状态
careTaker . add ( originator . setSateToMemento ());
originator . setState ( "State #3" );
// 保存状态
careTaker . add ( originator . setSateToMemento ());
originator . setState ( "State #4" );
Log . e ( "---" , "Current State: " + originator . getState ());
// 得到保存的状态
String fromMemento1 = originator . getStateFromMemento ( careTaker . get ( 0 ));
Log . e ( "---" , "First Saved State: " + fromMemento1 );
String fromMemento2 = originator . getStateFromMemento ( careTaker . get ( 1 ));
Log . e ( "---" , "Second Saved State: " + fromMemento2 );
/*
* /---: Current State: State #4
* /---: First Saved State: State #2
* /---: Second Saved State: State #3
*/
จัดเตรียมวิธีการประเมินไวยากรณ์หรือสำนวนของภาษาและเป็นรูปแบบพฤติกรรม รูปแบบนี้ใช้อินเทอร์เฟซนิพจน์ที่ตีความบริบทเฉพาะ โหมดนี้ใช้ในการแยกวิเคราะห์ SQL กลไกการประมวลผลสัญลักษณ์ ฯลฯ
ยกตัวอย่างประโยคอธิบาย ขั้นตอนหน่วยขั้นต่ำ:
1. สร้างอินเทอร์เฟซนิพจน์ Expression
public interface Expression {
public boolean interpreter ( String content );
}
2. สร้างคลาสเอนทิตีที่ใช้อินเทอร์เฟซข้างต้น TerminalExpression, OrExpression และนิพจน์
public class TerminalExpression implements Expression {
private String data ;
public TerminalExpression ( String data ) {
this . data = data ;
}
@ Override
public boolean interpreter ( String content ) {
// 是包含判断
return content . contains ( data );
}
}
public class OrExpression implements Expression {
private Expression expression1 ;
private Expression expression2 ;
public OrExpression ( Expression expression1 , Expression expression2 ) {
this . expression1 = expression1 ;
this . expression2 = expression2 ;
}
@ Override
public boolean interpreter ( String content ) {
return expression1 . interpreter ( content ) || expression2 . interpreter ( content );
}
}
public class AndExpression implements Expression {
private Expression expression1 ;
private Expression expression2 ;
public AndExpression ( Expression expression1 , Expression expression2 ) {
this . expression1 = expression1 ;
this . expression2 = expression2 ;
}
@ Override
public boolean interpreter ( String content ) {
return expression1 . interpreter ( content ) && expression2 . interpreter ( content );
}
}
3. ใช้คลาส Expression เพื่อสร้างกฎและแยกวิเคราะห์
/**
* 规则:jingbin 和 youlookwhat 是男性
*/
public static Expression getMaleExpression () {
TerminalExpression jingbin = new TerminalExpression ( "jingbin" );
TerminalExpression youlookwhat = new TerminalExpression ( "youlookwhat" );
return new OrExpression ( jingbin , youlookwhat );
}
/**
* 规则:Julie 是一个已婚的女性
*/
public static Expression getMarriedWomanExpression () {
TerminalExpression julie = new TerminalExpression ( "Julie" );
TerminalExpression married = new TerminalExpression ( "Married" );
return new AndExpression ( julie , married );
}
Expression maleExpression = getMaleExpression ();
// jingbin is male: true
Log . e ( "---" , "jingbin is male: " + maleExpression . interpreter ( "jingbin" ));
Expression womanExpression = getMarriedWomanExpression ();
// Julie is married woman: true
Log . e ( "---" , "Julie is married woman: " + womanExpression . interpreter ( "Married Julie" ));
รูปแบบห่วงโซ่ความรับผิดชอบสร้างห่วงโซ่ของวัตถุผู้รับสำหรับการร้องขอ รูปแบบนี้จะแยกระหว่างผู้ส่งและผู้รับคำขอตามประเภทของคำขอ รูปแบบการออกแบบประเภทนี้เป็นรูปแบบพฤติกรรม ในรูปแบบนี้ โดยทั่วไปแล้วเครื่องรับแต่ละตัวจะมีการอ้างอิงถึงเครื่องรับอื่น หากออบเจ็กต์ไม่สามารถจัดการคำขอได้ ก็จะส่งคำขอเดียวกันไปยังผู้รับรายถัดไป และต่อๆ ไป
ยกตัวอย่างบันทึกการพิมพ์ใน Android Studio ขั้นตอนขั้นต่ำของหน่วยคือ:
1. สร้างคลาสตัวบันทึกนามธรรม AbstractLogger
public abstract class AbstractLogger {
public static int INFO = 1 ;
public static int DEBUG = 2 ;
public static int ERROR = 3 ;
protected int level ;
// 责任链中的下一个元素
protected AbstractLogger nextLogger ;
public void setNextLogger ( AbstractLogger nextLogger ) {
this . nextLogger = nextLogger ;
}
public void logMessage ( int level , String message ) {
if ( this . level <= level ) {
write ( message );
}
// 递归效果,不断调用下一级 logMessage
if ( nextLogger != null ) {
nextLogger . logMessage ( level , message );
}
}
protected abstract void write ( String message );
}
2. สร้างคลาสเอนทิตีที่ขยายคลาสตัวบันทึก
public class ConsoleLogger extends AbstractLogger {
public ConsoleLogger ( int level ) {
this . level = level ;
}
@ Override
protected void write ( String message ) {
Log . e ( "---" , "Standard Console::Logger " + message );
}
}
public class FileLogger extends AbstractLogger {
public FileLogger ( int level ) {
this . level = level ;
}
@ Override
protected void write ( String message ) {
Log . e ( "---" , "File::Logger " + message );
}
}
public class ErrorLogger extends AbstractLogger {
public ErrorLogger ( int level ) {
this . level = level ;
}
@ Override
protected void write ( String message ) {
Log . e ( "---" , "Error Console::Logger " + message );
}
}
3. สร้างตัวบันทึกประเภทต่างๆ กำหนดระดับข้อผิดพลาดที่แตกต่างกัน และภายในตัวบันทึกแต่ละตัวให้ตั้งค่าตัวบันทึกถัดไป ตัวบันทึกถัดไปในแต่ละตัวบันทึกแสดงถึงส่วนหนึ่งของห่วงโซ่
public static AbstractLogger getChainOfLoggers () {
ErrorLogger errorLogger = new ErrorLogger ( AbstractLogger . ERROR );
FileLogger fileLogger = new FileLogger ( AbstractLogger . DEBUG );
ConsoleLogger consoleLogger = new ConsoleLogger ( AbstractLogger . INFO );
errorLogger . setNextLogger ( fileLogger );
fileLogger . setNextLogger ( consoleLogger );
return errorLogger ;
}
AbstractLogger logger = getChainOfLoggers ();
// ---: Standard Console::Logger this is an information.
logger . logMessage ( AbstractLogger . INFO , "this is an information." );
// ---: File::Logger this is a debug level information.
// ---: Standard Console::Logger this is a debug level information.
logger . logMessage ( AbstractLogger . DEBUG , "this is a debug level information." );
// ---: Error Console::Logger this is a error level information.
// ---: File::Logger this is a error level information.
// ---: Standard Console::Logger this is a error level information.
logger . logMessage ( AbstractLogger . ERROR , "this is a error level information." );
ในรูปแบบผู้เยี่ยมชม เราใช้คลาสผู้เยี่ยมชมซึ่งเปลี่ยนอัลกอริธึมการดำเนินการของคลาสองค์ประกอบ ด้วยวิธีนี้ อัลกอริธึมการดำเนินการขององค์ประกอบสามารถเปลี่ยนแปลงได้เมื่อผู้เยี่ยมชมเปลี่ยนแปลง รูปแบบการออกแบบประเภทนี้เป็นรูปแบบพฤติกรรม ตามสคีมา วัตถุองค์ประกอบได้ยอมรับวัตถุผู้เยี่ยมชม เพื่อให้วัตถุผู้เยี่ยมชมสามารถจัดการการดำเนินการกับวัตถุองค์ประกอบได้
ยกตัวอย่างส่วนประกอบของคอมพิวเตอร์แสดงผล โดยหลักๆ จะนำไปใช้ในห้าขั้นตอน:
1. กำหนดอินเทอร์เฟซที่แสดงถึงองค์ประกอบ
public interface ComputerPart {
public void accept ( ComputerPartVisitor computerPartVisitor );
}
2. สร้างคลาสเอนทิตีที่ขยายคลาสข้างต้น คีย์บอร์ด จอภาพ เมาส์ คอมพิวเตอร์
public class Computer implements ComputerPart {
private ComputerPart [] parts ;
public Computer () {
this . parts = new ComputerPart []{ new Mouse (), new Keyboard (), new Monitor ()};
}
@ Override
public void accept ( ComputerPartVisitor computerPartVisitor ) {
for ( ComputerPart part : parts ) {
part . accept ( computerPartVisitor );
}
computerPartVisitor . visit ( this );
}
}
public class Mouse implements ComputerPart {
@ Override
public void accept ( ComputerPartVisitor computerPartVisitor ) {
computerPartVisitor . visit ( this );
}
}
3. กำหนดอินเทอร์เฟซที่แสดงถึงผู้เยี่ยมชม
public interface ComputerPartVisitor {
public void visit ( Computer computer );
public void visit ( Mouse mouse );
public void visit ( Keyboard keyboard );
public void visit ( Monitor monitor );
}
4. สร้างผู้เยี่ยมชมเอนทิตีที่ใช้คลาสข้างต้น
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@ Override
public void visit ( Computer computer ) {
Log . e ( "---" , "Displaying Computer." );
}
@ Override
public void visit ( Mouse mouse ) {
Log . e ( "---" , "Displaying Mouse." );
}
@ Override
public void visit ( Keyboard keyboard ) {
Log . e ( "---" , "Displaying Keyboard." );
}
@ Override
public void visit ( Monitor monitor ) {
Log . e ( "---" , "Displaying Monitor." );
}
}
5. ใช้ ComputerPartDisplayVisitor เพื่อแสดงส่วนประกอบของคอมพิวเตอร์
ComputerPart computer = new Computer ();
computer . accept ( new ComputerPartDisplayVisitor ());
/*
*打印:
*---: Displaying Mouse.
*---: Displaying Keyboard.
*---: Displaying Monitor.
*---: Displaying Computer.
*/