此文章部分來於網絡,爲了學習總結。java
介紹:從一個對象再建立另外一個對象,而不需知道任何細節。面試
一、兩種表現形式數據庫
(1)簡單形式apache
(2)登記形式設計模式
這兩種表現形式僅僅是原型模式的不一樣實現。安全
二、倆種克隆方法網絡
(1)淺複製ide
介紹:只克隆值傳遞的數據(好比基本數據類型、String),而不復制它所引用的對象,就是對其餘對象的引用都指向原來的對象。 注意:可實現Cloneable接口。
(2)深複製學習
介紹:除了淺度克隆要克隆的值外,還負責克隆引用類型的數據,把要複製的對象所引用的對象都複製了一遍。 注意:採用字節流寫入寫出對象,全部對象必須實現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; } } }
介紹:將重複的部分上升到父類。ui
舉例:公司的面試題是相同的,只有應聘者的答案不一樣,因此相同的問題在父類中表現,子類只用做記錄答案。
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(); } }
介紹:定義一個高層接口,使得子系統更容易使用。
介紹:將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。
舉例:遇到多個構造器參數時考慮使用構建器,而不是重疊構造器模式或JavaBean模式調用setter方法。(靜態工廠和構造器有個共同的侷限性:它們不能很好地擴展大量的可選參數)
/** * 構建器模式 * @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(); //客戶端調用
缺點:構建器模式可能比重疊構造器更加冗長,參數多時使用較好。若是構建器沒有在最初使用,後期使用會有些難以控制,一般一開始就使用構建器。
優勢:構建器比重疊構造器的客戶端代碼易讀寫。比JavaBean更安全。
舉例:項目中可能須要訪問多種類型的數據庫,數據庫訪問與邏輯業務應該獨立分開,只需在客戶端建立工廠類。
介紹:將對象轉換的邏輯判斷轉移到不一樣狀態的類中,來簡化複雜的邏輯判斷。若是邏輯判斷很簡單就不須要用此模式了。
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("當前狀態: " + 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()); // 建立下一個邏輯判斷 } } 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(); } }
介紹:系統的數據和行爲都正確,但接口不符時,使得一個原有對象與某個接口匹配。
舉例:假如巴西隊中有中國球員,防止語言間的差別,中國球員須要翻譯來與團隊交流。
介紹:捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。以後可恢復以前的狀態。
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<Component> list = new ArrayList<Component>(); 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<Object> items = new ArrayList<Object>(); @Override public Iterator createIterator() { // TODO Auto-generated method stub return new ConcreteIterator(this); } public int count() { return items.size(); } public Object get(int index) { return items.get(index); } public void add(Object obj) { items.add(obj); } } /** * 具體迭代器 * @author chenguyan * @date 2017年6月16日 */ public class ConcreteIterator extends Iterator { private ConcreteAggregate concreteAggregate; private int current = 0; public ConcreteIterator(ConcreteAggregate concrete) { // TODO Auto-generated constructor stub this.concreteAggregate = concrete; } @Override public Object first() { // TODO Auto-generated method stub return concreteAggregate.get(0); } @Override public Object next() { // TODO Auto-generated method stub current++; if (current >= concreteAggregate.count()) { return null; } return concreteAggregate.get(current); } @Override public boolean isDone() { // TODO Auto-generated method stub return current > concreteAggregate.count() ? true : false; } @Override public Object currentItem() { // TODO Auto-generated method stub return concreteAggregate.get(current); } } /** * 客戶端 * @author chenguyan * @date 2017年6月16日 */ public class Client { public static void main(String[] args) { ConcreteAggregate concrete = new ConcreteAggregate(); concrete.add("a"); concrete.add("b"); concrete.add("c"); concrete.add("d"); concrete.add("e"); Iterator ite = new ConcreteIterator(concrete); System.out.println(ite.first().toString()); while (!ite.isDone()) { Object item = ite.next(); System.out.println(item != null ? item.toString() : ""); } } }
爲何會採用抽象類的方式來實現迭代器呢?由於能夠有不一樣的迭代順序,從前向後、從後向前等,因此隨意新增迭代器的實現類來達到迭代順序的不一樣,並且客戶端修改部分較少。
介紹:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
/** * 雙重鎖定 * @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; } }
介紹:按各自的功能進行分類,使他們能夠獨立運行。
舉例:手機的品牌與軟件都會存在不兼容的狀況,這是由於手機廠商即作硬件又作軟件,沒有統一的標準。若是有一個統一的硬件廠商設計標準,手機廠商只負責軟件,這樣每一個手機廠商開發的軟件就不存在不兼容的狀況了。
十5、命令模式
介紹:將請求命令封裝成對象,從而使你可用不一樣的請求命令來操做對象。
/** * 命令 * @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("正在執行烤肉"); } } /** * 接收人 * @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<Command> commandList = new ArrayList<Command>(); 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(); } }
介紹:若是兩個類沒必要彼此通訊,那麼這兩個類就不該當發生直接的相互做用。強調類之間的鬆耦合。
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){ ... } } }