摘要:舉例遇到多個構造器參數(shù)時考慮使用構建器,而不是重疊構造器模式或模式調用方法。靜態(tài)工廠和構造器有個共同的局限性它們不能很好地擴展大量的可選參數(shù)構建器模式年月日客戶端調用缺點構建器模式可能比重疊構造器更加冗長,參數(shù)多時使用較好。
設計模式
此文章部分來于網絡,為了學習總結。
一、原型模式(Prototype)介紹:從一個對象再創(chuàng)建另一個對象,而不需知道任何細節(jié)。
1、兩種表現(xiàn)形式
(1)簡單形式
(2)登記形式
這兩種表現(xiàn)形式僅僅是原型模式的不同實現(xiàn)。
2、倆種克隆方法
(1)淺復制
介紹:只克隆值傳遞的數(shù)據(比如基本數(shù)據類型、String),而不復制它所引用的對象,就是對其他對象的引用都指向原來的對象。 注意:可實現(xiàn)Cloneable接口。
(2)深復制
介紹:除了淺度克隆要克隆的值外,還負責克隆引用類型的數(shù)據,把要復制的對象所引用的對象都復制了一遍。 注意:采用字節(jié)流寫入寫出對象,所有對象必須實現(xiàn)Serializable。Thread和Socket對象必須設置transient,不予復制。
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class Prototype implements Cloneable, Serializable{ @Override protected Object clone() throws CloneNotSupportedException { //淺克隆 // TODO Auto-generated method stub Prototype prototype = (Prototype) super.clone(); return prototype; } public Object deepClone(){ //深克隆 try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); return null; } } }二、模板方法模式
介紹:將重復的部分上升到父類。
舉例:公司的面試題是相同的,只有應聘者的答案不同,所以相同的問題在父類中表現(xiàn),子類只用作記錄答案。
public class TestPaper { public void testQuestion1(){ System.out.println("1 + 1 = "); System.out.println("答案是:" + answer()); } protected String answer(){ return ""; } } public class TestPaperA extends TestPaper { @Override protected String answer() { // TODO Auto-generated method stub return "2"; } } public class Client { public static void main(String[] args) { TestPaper testPagerA = new TestPaperA(); testPagerA.question(); } }三、外觀模式(Fade)
介紹:定義一個高層接口,使得子系統(tǒng)更容易使用。
四、建造者模式(Builder)介紹:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創(chuàng)建不同的表示。
舉例:遇到多個構造器參數(shù)時考慮使用構建器,而不是重疊構造器模式或JavaBean模式調用setter方法。(靜態(tài)工廠和構造器有個共同的局限性:它們不能很好地擴展大量的可選參數(shù))
/** * 構建器模式 * @author alex * @date 2017年4月6日 */ public class A { private final int a; private final int b; private final int c; public static class A_son { private final int a; private final int b; private int c = 0; public A_son(int a, int b) { this.a = a; this.b = b; } public A_son c(int val) { c = val; return this; } public A build() { return new A(this); } } public A(A_son a_son) { a = a_son.a; b = a_son.b; c = a_son.c; } } A a = new A.A_son(12, 12).c(12).build(); //客戶端調用
缺點:構建器模式可能比重疊構造器更加冗長,參數(shù)多時使用較好。如果構建器沒有在最初使用,后期使用會有些難以控制,通常一開始就使用構建器。
優(yōu)點:構建器比重疊構造器的客戶端代碼易讀寫。比JavaBean更安全。
五、觀察者模式 六、工廠方法模式舉例:項目中可能需要訪問多種類型的數(shù)據庫,數(shù)據庫訪問與邏輯業(yè)務應該獨立分開,只需在客戶端創(chuàng)建工廠類。
七、抽象工廠模式 八、狀態(tài)模式介紹:將對象轉換的邏輯判斷轉移到不同狀態(tài)的類中,來簡化復雜的邏輯判斷。如果邏輯判斷很簡單就不需要用此模式了。
abstract class State { public abstract void handle(Context context); } public class Context { private State state; public Context(State state) { this.state = state; } public void request() { state.handle(this); } public State getState() { System.out.println("當前狀態(tài): " + state.getClass().toString()); return state; } public void setState(State state) { this.state = state; getState(); } } public class ConcreteStateA extends State { @Override public void handle(Context context) { // TODO Auto-generated method stub context.setState(new ConcreteStateB()); // 創(chuàng)建下一個邏輯判斷 } } public class ConcreteStateB extends State { @Override public void handle(Context context) { // TODO Auto-generated method stub context.setState(new ConcreteStateA()); } } public class Test { public static void main(String[] args) { Context context = new Context(new ConcreteStateA()); context.request(); context.request(); context.request(); } }九、適配器模式
介紹:系統(tǒng)的數(shù)據和行為都正確,但接口不符時,使得一個原有對象與某個接口匹配。
舉例:假如巴西隊中有中國球員,防止語言間的差異,中國球員需要翻譯來與團隊交流。
十、備忘錄模式介紹:捕獲一個對象的內部狀態(tài),并在該對象之外保存這個狀態(tài)。之后可恢復之前的狀態(tài)。
public class Originator { private String state; public Memento createMemento() { return new Memento(state); } public void setMemento(Memento memento) { state = memento.getState(); } public void show() { System.out.println("state =" + state); } public String getState() { return state; } public void setState(String state) { this.state = state; } } public class Caretaker { private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = 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; } } public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Originator originator = new Originator(); originator.setState("on"); originator.show(); Caretaker caretaker = new Caretaker(); caretaker.setMemento(originator.createMemento()); originator.setState("asdasd"); originator.show(); originator.setMemento(caretaker.getMemento()); originator.show(); } }
缺點:易消耗內存。
十一、組合模式介紹:將對象組合成樹形結構來表示部分-整體,使部分與整體具有一致性。
public abstract class Component { protected String name; public Component(String name) { this.name = name; } public abstract void add(Component c); public abstract void remove(Component c); public abstract void display(int depth); } import org.apache.commons.lang.StringUtils; public class Leaf extends Component { public Leaf(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void add(Component c) { // TODO Auto-generated method stub System.out.println("Don"t add component"); } @Override public void remove(Component c) { // TODO Auto-generated method stub System.out.println("Don"t remove component"); } @Override public void display(int depth) { // TODO Auto-generated method stub System.out.println(StringUtils.repeat("-", depth) + name); } } import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; public class Composite extends Component { private List十二、迭代器模式list = new ArrayList (); public Composite(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void add(Component c) { // TODO Auto-generated method stub list.add(c); } @Override public void remove(Component c) { // TODO Auto-generated method stub list.remove(c); } @Override public void display(int depth) { // TODO Auto-generated method stub System.out.println(StringUtils.repeat("-", depth) + name); for (Component component : list) { component.display(depth + 2); } } } public class Test { public static void main(String[] args) { Composite root = new Composite("root"); root.add(new Leaf("Leaf A")); root.add(new Leaf("Leaf B")); Composite comp = new Composite("Composite X"); comp.add(new Leaf("Leaf XA")); comp.add(new Leaf("Leaf XB")); root.add(comp); Composite comp2 = new Composite("Composite Y"); root .add(comp2); root.display(1); } }
介紹:提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內部表示
/** * 迭代器抽象 * @author chenguyan * @date 2017年6月16日 */ public abstract class Iterator { public abstract Object first(); public abstract Object next(); public abstract boolean isDone(); public abstract Object currentItem(); } /** * 聚集抽象 * @author chenguyan * @date 2017年6月16日 */ public abstract class Aggregate { public abstract Iterator createIterator(); } /** * 具體聚集 * @author chenguyan * @date 2017年6月16日 */ public class ConcreteAggregate extends Aggregate { private List
為什么會采用抽象類的方式來實現(xiàn)迭代器呢?因為可以有不同的迭代順序,從前向后、從后向前等,所以隨意新增迭代器的實現(xiàn)類來達到迭代順序的不同,而且客戶端修改部分較少。
十三、單例模式介紹:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
/** * 雙重鎖定 * @date 2017年7月3日 */ public class Singleton { private static Singleton singleton; private static Object syncObj = new Object(); public static Singleton getInstance() { if (singleton == null) { synchronized (syncObj) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }十四、橋接模式
介紹:按各自的功能進行分類,使他們可以獨立運行。
舉例:手機的品牌與軟件都會存在不兼容的情況,這是因為手機廠商即做硬件又做軟件,沒有統(tǒng)一的標準。如果有一個統(tǒng)一的硬件廠商設計標準,手機廠商只負責軟件,這樣每個手機廠商開發(fā)的軟件就不存在不兼容的情況了。
十五、命令模式
介紹:將請求命令封裝成對象,從而使你可用不同的請求命令來操作對象。
/** * 命令 * @date 2017年8月11日 */ public abstract class Command { private Recipient recipient; public void setRecipient(Recipient recipient) { this.recipient = recipient; } public abstract void doing(); } /** * 烤菜命令 * @date 2017年8月11日 */ public class RoastVegetablesCommand extends Command { private Recipient recipient; @Override public void setRecipient(Recipient recipient) { // TODO Auto-generated method stub this.recipient = recipient; } @Override public void doing() { // TODO Auto-generated method stub System.out.println("正在烤菜"); } } /** * 烤肉命令 * @date 2017年8月11日 */ public class RoastMeatCommand extends Command { private Recipient recipient; @Override public void setRecipient(Recipient recipient) { // TODO Auto-generated method stub this.recipient = recipient; } @Override public void doing() { // TODO Auto-generated method stub System.out.println("正在執(zhí)行烤肉"); } } /** * 接收人 * @date 2017年8月11日 */ public class Recipient { private String name; private String job; public Recipient(String name, String job) { this.name = name; this.job = job; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } } /** * 服務員 * @date 2017年8月11日 */ public class Waiter { private List設計原則 一、迪米特法則commandList = new ArrayList (); public void addOrder(Command command) { if (!commandList.contains(command)) { commandList.add(command); } } public void notifyCommand() { for (Command command : commandList) { command.doing(); } } } public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Recipient recipient = new Recipient("大廚", "大廚"); Command roastMeatCommand = new RoastMeatCommand(); Command roastVegetablesCommand = new RoastVegetablesCommand(); roastMeatCommand.setRecipient(recipient); roastVegetablesCommand.setRecipient(recipient); Waiter waiter = new Waiter(); waiter.addOrder(roastMeatCommand); waiter.addOrder(roastVegetablesCommand); waiter.notifyCommand(); } }
介紹:如果兩個類不必彼此通信,那么這兩個類就不應當發(fā)生直接的相互作用。強調類之間的松耦合。
反射機制 一、調用私有域和方法(setAccessible)class Employee{ private int id; private String name; private int age; public Employee(){} public Employee(int id, String name, int age){ this.id = id; this.name = name; this.age = age; } private void setId(int id){ this.id = id; } private int judge(int id){ return this.id - id; } private String sayHalo(String name){ return "Halo" + name; } } public class PrivateTest{ public static void main(String[] args){ Employee em = new Employee(1, "Alex", 22); Class> emClass = em.getClass(); Method judgeMethod = emClass.getDeclaredMethod("judge", new Class[]{Integer.TYPE}); //獲取聲明的方法 judgeMethod.setAccessible(true); //使成員可以訪問 Method[] allMethods = emClass.getDeclaredMethods(); //獲取所有聲明的方法 AccessibleObject.setAccessible(allMethods, true); judgeMethod.invoke(em, new Object[]{3}); //通過反射訪問 //or... for(Method method : allMethods){ ... } } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66917.html
摘要:學習編程的本最佳書籍這些書涵蓋了各個領域,包括核心基礎知識,集合框架,多線程和并發(fā),內部和性能調優(yōu),設計模式等。擅長解釋錯誤及錯誤的原因以及如何解決簡而言之,這是學習中并發(fā)和多線程的最佳書籍之一。 showImg(https://segmentfault.com/img/remote/1460000018913016); 來源 | 愿碼(ChainDesk.CN)內容編輯 愿碼Slo...
摘要:基礎知識復習后端掘金的作用表示靜態(tài)修飾符,使用修飾的變量,在中分配內存后一直存在,直到程序退出才釋放空間。將對象編碼為字節(jié)流稱之為序列化,反之將字節(jié)流重建成對象稱之為反序列化。 Java 學習過程|完整思維導圖 - 后端 - 掘金JVM 1. 內存模型( 內存分為幾部分? 堆溢出、棧溢出原因及實例?線上如何排查?) 2. 類加載機制 3. 垃圾回收 Java基礎 什么是接口?什么是抽象...
摘要:有不少朋友問,除了掌握語法,還要系統(tǒng)學習哪些相關的技術,今天分享一個,互聯(lián)網技術學習路線圖。群內已經有小伙伴將知識體系整理好源碼,筆記,學習視頻,歡迎加群免費取。 showImg(https://segmentfault.com/img/remote/1460000015926035); 我們都知道android依賴于Java,五六年后進入瓶頸期,很多人都學習了后臺業(yè)務關的知識。當然我...
摘要:進階多線程開發(fā)關鍵技術后端掘金原創(chuàng)文章,轉載請務必將下面這段話置于文章開頭處保留超鏈接。關于中間件入門教程后端掘金前言中間件 Java 開發(fā)人員最常犯的 10 個錯誤 - 后端 - 掘金一 、把數(shù)組轉成ArrayList 為了將數(shù)組轉換為ArrayList,開發(fā)者經常... Java 9 中的 9 個新特性 - 后端 - 掘金Java 8 發(fā)布三年多之后,即將快到2017年7月下一個版...
閱讀 1369·2021-10-13 09:39
閱讀 1333·2021-09-23 11:22
閱讀 2243·2019-08-30 14:05
閱讀 1059·2019-08-29 17:03
閱讀 771·2019-08-29 16:24
閱讀 2227·2019-08-29 13:51
閱讀 656·2019-08-29 13:00
閱讀 1290·2019-08-29 11:24