最近在讀秦小波的《設計模式之禪》。本文又是一篇長達2000行的又水又長的筆記,記錄書中所講23個設計模式中的22個,基本上是將書中講的各個設計模式的定義、優勢、缺點、適用場景、demo抄下來了。推薦去閱讀原書,這是一位學識豐富且有一個有趣的靈魂的做者所寫,原書中每一個設計模式的講解都有一個十分有趣的例子,藉助這些例子能夠很好的加深理解和記憶。
設計模式感受都是相通的,以前看過一本《JavaScript設計模式與開發實踐》,其實都是講的一回事,只是由於語言特性緣由在實現方面有所區別,這本書的做者也有一個有趣的靈魂,我如今都還記得代理模式中「小明追美眉」的故事,也推薦閱讀。java
定義:算法
確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例spring
示例:編程
public class Singleton { private static Singleton singleton = new Singleton(); // 私有化構造 private Singleton() { } // 獲取實例 public static Singleton getInstance() { return singleton; } // 類中其餘方法儘可能是static的 public static void otherMethod() { } }
優勢:設計模式
缺點:安全
適用場景:數據結構
定義:框架
定義一個用於建立對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到其子類dom
示例:ide
/** * 抽象產品 */ public abstract class Product { public void method1() { System.out.println("method1"); } abstract public void method2(); } /** * 具體的一個產品 */ public class ProductA extends Product { public void method2() { System.out.println("productA method2"); } } /** * 具體的一個產品 */ public class ProductB extends Product { public void method2() { System.out.println("productB method2"); } } /** * 抽象工廠 */ public abstract class Factory { public abstract <T extends Product> T createProduct(Class<T> clazz); } /** * 具體工廠 */ public class ProductFactory1 extends Factory { public <T extends Product> T createProduct(Class<T> clazz) { Product product = null; try { product = (Product) Class.forName(clazz.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return (T) product; } } /** * 測試類 */ public class FactoryTest { @Test public void test() { Factory factory = new ProductFactory1(); ProductA productA = factory.createProduct(ProductA.class); ProductB productB = factory.createProduct(ProductB.class); productA.method2(); productB.method2(); } }
優勢:
使用場景:
工廠模式擴展:
/** * 靜態工廠 */ public class ProductFactory2 { private ProductFactory2() { } static Product createProduct(Class<Product> clazz) { Product product = null; try { product = (Product) Class.forName(clazz.getName()).newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } return product; } }
多工廠模式
實現單例模式
延遲初始化
定義:
爲建立一組相關或相互依賴的對象提供一個接口,並且無須指定它們的具體類
示例:
public class Factory { public ProductA createProductA() { return new ProductA(); } public ProductB createProductB() { return new ProductB(); } }
優勢:
缺點:
適用場景:
一個對象族(或是一組沒有任何關係的對象)都有相同的約束,則可使用抽象工廠模式。就是一堆類有相同的父類
定義:
定義一個操做中的算法的框架,而將一些步驟延遲到子類中。使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟
示例:
/** * 模板類 */ public abstract class TemplateClass { protected abstract void method1(); protected abstract void method2(); /** * 模板方法 */ public void templateMethod() { method1(); method2(); } } /** * 根據模板類建立的類 */ public class TemplateSubClass1 extends TemplateClass { protected void method1() { System.out.println("1 method1"); } protected void method2() { System.out.println("1 method2"); } } /** * 根據模板類建立的類 */ public class TemplateSubClass2 extends TemplateClass { protected void method1() { System.out.println("2 method1"); } protected void method2() { System.out.println("2 method2"); } } /** * 測試類 */ public class TemplateTest { @Test public void test() { TemplateSubClass1 templateSubClass1 = new TemplateSubClass1(); templateSubClass1.templateMethod(); TemplateSubClass2 templateSubClass2 = new TemplateSubClass2(); templateSubClass2.templateMethod(); } }
優勢:
缺點:
子類對父類產生了影響,在複雜的項目中,會帶來代碼閱讀的難度,會讓新手難以適應
適用場景:
多個子類有公有的方法,而且邏輯基本相同
模板方法模式擴展:
能夠經過定義開關的形式,調整模板方法的執行流程
定義:
將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示
示例:
public class Product { private String name; private int price; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } } public class ProductBuilder { private Product product = new Product(); public void buildName(String name) { product.setName(name); } public void buildPrice(Integer price) { product.setPrice(price); } public Product create() { return product; } }
優勢:
缺點:
適用場景:
定義:
爲其餘對象提供一種代理以控制對這個對象的訪問
示例:
/** * 被代理類接口 */ public interface Subject { void doSomething(); } /** * 真實被代理類 */ public class RealSubject implements Subject { public void doSomething() { System.out.println("RealSubject doSomething"); } } /** * 代理類 */ public class SubjectProxy implements Subject { private Subject subject = null; public SubjectProxy() { this.subject = new RealSubject(); } public void doSomething() { System.out.println("doSomething 被代理了"); this.subject.doSomething(); } } /** * 測試類 */ public class SubjectProxyTest { @Test public void test() { SubjectProxy subjectProxy = new SubjectProxy(); subjectProxy.doSomething(); } }
優勢:
適用場景:
代理模式擴展:
就是示例那個,調用方知道代理的存在(相似正向代理)
調用方不知道代理的存在(相似反向代理)
/** * 真實被代理類 */ public class RealSubject implements Subject { public RealSubject(Subject subject) throws ClassNotFoundException { // 注意這裏 if (subject == null) { throw new ClassNotFoundException(); } } public void doSomething() { System.out.println("RealSubject doSomething"); } } /** * 代理類 */ public class SubjectProxy implements Subject { private Subject subject = null; public SubjectProxy() { // 注意這裏 try { this.subject = new RealSubject(this); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public void doSomething() { System.out.println("doSomething 被代理了"); this.subject.doSomething(); } } /*** * 測試類 */ public class ProxyTest { @Test public void test() { SubjectProxy subjectProxy = new SubjectProxy(); subjectProxy.doSomething(); } @Test public void test2() throws ClassNotFoundException { // 會報錯的 // RealSubject realSubject = new RealSubject(); // realSubject.doSomething(); } }
必須經過真實角色查找到代理角色,不然你不能訪問
感受意義不是太大
動態代理是在實現階段不用關心代理誰,而在運行階段才指定代理哪個對象
/** * 通知接口 */ public interface Advice { public void exec(); } /** * 通知類 */ public class BeforeAdvice implements Advice { public void exec() { System.out.println("前置通知執行了"); } } /** * 動態代理的handler */ public class MyInvocationHandler implements InvocationHandler { // 被代理對象 private Object target; public MyInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 尋找JoinPoint連結點 if (true) { new BeforeAdvice().exec(); } // 執行被代理的方法 return method.invoke(this.target, args); } } /** * 動態代理類 */ public class SubjectDynamicProxy { public static Subject newInstance(Subject subject) { ClassLoader classLoader = subject.getClass().getClassLoader(); Class<?>[] interfaces = subject.getClass().getInterfaces(); InvocationHandler invocationHandler = new MyInvocationHandler(subject); return (Subject) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); } } /** * 測試類 */ public class ProxyTest { @Test public void test() { Subject subject = new RealSubject(); Subject proxySubject = SubjectDynamicProxy.newInstance(subject); proxySubject.doSomething(); } }
使用jdk的動態代理要求被代理類必須實現一個接口,CGLIB動態代理沒有這個要求。
spring 的aop就是使用的動態代理技術實現的
定義:
用原型實例指定建立對象的種類,而且經過拷貝這些原型建立新的對象。即基於對象建立對象,而不是類
示例:
public class Prototype implements Cloneable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected Prototype clone() throws CloneNotSupportedException { // 關鍵就是這個東西 return (Prototype) super.clone(); } }
優勢:
適用場景:
注意點:
定義:
用一箇中介對象封裝一系列的對象交互,中介者使各對象不須要顯示地相互做用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互
示例:
/** * 同事抽象類 */ public abstract class Colleagure { protected Mediator mediator; public Colleagure(Mediator mediator) { this.mediator = mediator; } } /** * 具體同事類 */ public class ConcreteColleagure1 extends Colleagure { public ConcreteColleagure1(Mediator mediator) { super(mediator); } public void selfMethod1() { System.out.println("ConcreteColleagure1 本身的業務邏輯"); } public void depMethod1() { // 依賴其餘對象的邏輯,給中介者處理 super.mediator.doSomething1(); } } /** * 具體同事類 */ public class ConcreteColleagure2 extends Colleagure { public ConcreteColleagure2(Mediator mediator) { super(mediator); } public void selfMethod1() { System.out.println("ConcreteColleagure2 本身的業務邏輯"); } public void depMethod1() { // 依賴其餘對象的邏輯,給中介者處理 super.mediator.doSomething2(); } } /** * 抽象中介者 */ public abstract class Mediator { protected ConcreteColleagure1 concreteColleagure1; protected ConcreteColleagure2 concreteColleagure2; public abstract void doSomething1(); public abstract void doSomething2(); public ConcreteColleagure1 getConcreteColleagure1() { return concreteColleagure1; } public void setConcreteColleagure1(ConcreteColleagure1 concreteColleagure1) { this.concreteColleagure1 = concreteColleagure1; } public ConcreteColleagure2 getConcreteColleagure2() { return concreteColleagure2; } public void setConcreteColleagure2(ConcreteColleagure2 concreteColleagure2) { this.concreteColleagure2 = concreteColleagure2; } } /** * 具體中介者 */ public class ConcreteMediator extends Mediator { public void doSomething1() { super.concreteColleagure1.selfMethod1(); super.concreteColleagure2.selfMethod1(); } public void doSomething2() { super.concreteColleagure2.selfMethod1(); super.concreteColleagure1.selfMethod1(); } } /** * 測試類 */ public class MediatorTest { @Test public void test() { Mediator mediator = new ConcreteMediator(); ConcreteColleagure2 concreteColleagure2 = new ConcreteColleagure2(mediator); ConcreteColleagure1 concreteColleagure1 = new ConcreteColleagure1(mediator); mediator.setConcreteColleagure1(concreteColleagure1); mediator.setConcreteColleagure2(concreteColleagure2); concreteColleagure1.depMethod1(); concreteColleagure2.depMethod1(); } }
優勢:
中介者模式的優勢就是減小類間的依賴,把原有的一對多的依賴變成了一對一的依賴,實現瞭解耦
適用場景:
定義:
將一個請求封裝成一個對象,從而讓你使用不一樣的請求把客戶端參數化,對請求排隊或者記錄請求日誌,能夠提供命令的撤銷和恢復功能
示例:
/** * 抽象接收者 */ public abstract class Recevier { public abstract void doSomething(); } /** * 具體的接收者 */ public class ConcreteRecevier1 extends Recevier { public void doSomething() { System.out.println("ConcreteRecevier1 業務邏輯"); } } /** * 具體的接收者 */ public class ConcreteRecevier2 extends Recevier { public void doSomething() { System.out.println("ConcreteRecevier2 業務邏輯"); } } /** * 抽象命令類 */ public abstract class Command { public abstract void execute(); } /** * 具體命令類 */ public class ConcreteCommand1 extends Command { Recevier recevier; public ConcreteCommand1(Recevier recevier) { this.recevier = recevier; } public ConcreteCommand1() { this(new ConcreteRecevier1()); } public void execute() { recevier.doSomething(); } } /** * 具體命令類 */ public class ConcreteCommand2 extends Command { Recevier recevier; public ConcreteCommand2(Recevier recevier) { this.recevier = recevier; } public ConcreteCommand2() { this(new ConcreteRecevier2()); } public void execute() { recevier.doSomething(); } } /** * 調用者 */ public class Invoker { private Command command; public void setCommand(Command command) { this.command = command; } public void action() { this.command.execute(); } } /** * 測試類 */ public class CommandTest { @Test public void test() { Command command = new ConcreteCommand1(); Command command1 = new ConcreteCommand2(); Invoker invoker = new Invoker(); invoker.setCommand(command); invoker.action(); invoker.setCommand(command1); invoker.action(); } }
優勢:
缺點:
定義:
使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有對象處理它爲止
示例:
/** * 處理級別 */ public enum Level { LEVEL1(1, "級別1"), LEVEL2(2, "級別2"), LEVEL3(3, "級別3"); private int code; private String msg; private Level(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public String getMsg() { return msg; } } /** * 請求封裝 */ public class Request { Level level; public Request(Level level) { this.level = level; } public Level getRequestLevel() { return this.level; } } /** * 響應封裝 */ public class Response { private int code; private String msg; public Response(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public String getMsg() { return msg; } } /** * 處理請求抽象 */ public abstract class Handler { private Handler nextHandler; public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; } public final Response handleMessage(Request request) { Response response = null; if (this.getHandleLevel().getCode() == request.getRequestLevel().getCode()) { // 本身處理 response = this.doRequest(request); } else { if (this.nextHandler != null) { // 交給下一我的處理 response = this.nextHandler.handleMessage(request); } else { response = new Response(-1, "無人處理"); } } return response; } // 獲取當前處理者可以處理的級別 protected abstract Level getHandleLevel(); // 處理請求 protected abstract Response doRequest(Request request); } /** * 具體處理請求的類 */ public class Level1Handler extends Handler { protected Level getHandleLevel() { return Level.LEVEL1; } protected Response doRequest(Request request) { return new Response(1, "第一個級別在Level1Handler處理了"); } } public class Level2Handler extends Handler { protected Level getHandleLevel() { return Level.LEVEL2; } protected Response doRequest(Request request) { return new Response(1, "第2個級別在Level2Handler處理了"); } } public class Level3Handler extends Handler { protected Level getHandleLevel() { return Level.LEVEL3; } protected Response doRequest(Request request) { return new Response(1, "第2個級別在Level3Handler處理了"); } } /** * 測試類 */ public class RequestChainTest { @Test public void test() { Level1Handler level1Handler = new Level1Handler(); Level2Handler level2Handler = new Level2Handler(); Level3Handler level3Handler = new Level3Handler(); level1Handler.setNextHandler(level2Handler); level2Handler.setNextHandler(level3Handler); Response response = level1Handler.handleMessage(new Request(Level.LEVEL2)); System.out.println(response.getCode()); System.out.println(response.getMsg()); } }
優勢:
定義:
動態地給一個對象添加一些額外的職責。就增長功能來講,裝飾模式相比生成子類更爲靈活
示例:
/** * 被裝飾類的抽象 */ public abstract class Component { public abstract void doSomething(); } /** * 具體被裝飾者 */ public class ConcreteComponent extends Component { public void doSomething() { System.out.println("被裝飾類的方法"); } } /** * 裝飾類 */ public class Decorator extends Component { private Component component; public Decorator(Component component) { this.component = component; } @Override public void doSomething() { this.component.doSomething(); } public void newMethod() { System.out.println("新增一個方法"); } }
優勢:
缺點:
多層的裝飾是比較複雜的
適用場景:
定義:
定義一組算法,將每一個算法都封裝起來,而且使它們之間能夠互換
示例:
/** * 策略接口 */ public interface Strategy { void doSomething(); } /** * 具體的策略 */ public class Strategy1 implements Strategy { public void doSomething() { System.out.println("第一種策略"); } } /** * 具體的策略 */ public class Strategy2 implements Strategy { public void doSomething() { System.out.println("第一種策略"); } } /** * 封裝策略 */ public class Context { private Strategy strategy; public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void execute() { this.strategy.doSomething(); } } /** * 測試類 */ public class StrategyTest { @Test public void test() { Context context = new Context(); context.setStrategy(new Strategy1()); context.execute(); } }
優勢:
缺點:
適用場景:
定義:
將一個類的接口變換成客戶端所期待的另外一種接口,從而使本來因接口不匹配而沒法在一塊兒工做的兩個類可以在一塊兒工做
示例:
/** * 目標角色 */ public interface Target { void request(); } /** * 源角色 */ public class Adaptee { public void doAnyThing() { System.out.println("doAnyThing"); } } /** * 適配器角色 */ public class Atapter extends Adaptee implements Target { public void request() { super.doAnyThing(); } }
優勢:
適用場景:
當要改一個已經在生產中適用的類時能夠考慮
定義:
它提供一種方法訪問一個容器對象中各個元素,而又不需暴露該對象的內部細節
示例:
不少集合類都實現了Iterable接口,就是迭代器模式
優勢:
遍歷方便,隱藏內部細節
定義:
將對象組合成樹形結構以表示「部分-總體」的層次結構,使得用戶對單個對象和組合對象的使用具備一致性
示例:
/** * 抽象構件 */ public abstract class Component { public void doSomething() { System.out.println("一些業務邏輯"); } } /** * 樹枝 */ public class Composite extends Component { /** * 子節點容器 */ private ArrayList<Component> componentArrayList = new ArrayList<Component>(); // 加節點 public void add(Component component) { this.componentArrayList.add(component); } // 刪節點 public void remove(Component component) { this.componentArrayList.remove(component); } // 獲取子節點 public ArrayList<Component> getChildren() { return this.componentArrayList; } } public class Leaf extends Component { @Override public void doSomething() { System.out.println("葉子"); super.doSomething(); } } /** * 測試類 */ public class CompositeTest { @Test public void test() { Composite root = new Composite(); root.doSomething(); Composite branch = new Composite(); Leaf leaf = new Leaf(); root.add(branch); branch.add(leaf); display(root); } private void display(Composite root) { for (Component component1 : root.getChildren()) { if (component1 instanceof Leaf) { component1.doSomething(); } else { display((Composite) component1); } } } }
優勢:
適用場景:
維護和展現部分-總體關係的場景
從一個總體中可以獨立出部分模塊或功能的場景
定義:
定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則全部依賴於它的對象都會獲得通知並被自動更新
示例:
/** * 觀察者接口 */ public interface Observer { // 更新 void update(Object object); } /** * 具體的觀察者 */ public class ConcreteObserver implements Observer { public void update(Object object) { System.out.println("收到了通知"+object.toString()); } } /** * 被觀察者抽象類 */ public abstract class Subject { private ArrayList<Observer> observers = new ArrayList<Observer>(); public void addObserver(Observer observer) { this.observers.add(observer); } public void removeObserver(Observer observer) { this.observers.remove(observer); } public void notifyObservers(Object object) { for (Observer observer : this.observers) { observer.update(object); } } } /** * 具體的被觀察者 */ public class ConcreteSubject extends Subject { public void doSomething() { super.notifyObservers("doSomething"); } } /** * 測試類 */ public class ObserverTest { @Test public void test() throws InterruptedException { Observer observer = new ConcreteObserver(); ConcreteSubject subject = new ConcreteSubject(); subject.addObserver(observer); Thread.sleep(1000); subject.doSomething(); } }
優勢:
缺點:
適用場景:
定義:
要求一個子系統的外部與其內部的通訊必須經過一個統一的對象進行。門面模式提供一個高層次的接口,使得子系統更易於使用
示例:
/** * 子系統 */ public class SubSystemA { public void doSomethingA() { System.out.println("doSomethingA"); } } /** * 子系統 */ public class SubSystemB { public void doSomethingB() { System.out.println("doSomethingB"); } } /** * 子系統 */ public class SubSystemC { public void doSomethingC() { System.out.println("doSomethingC"); } } /** * 門面 */ public class Facade { private SubSystemA subSystemA = new SubSystemA(); private SubSystemB subSystemB = new SubSystemB(); private SubSystemC subSystemC = new SubSystemC(); public void methodA() { subSystemA.doSomethingA(); } public void methodB() { subSystemB.doSomethingB(); } public void methodC() { subSystemC.doSomethingC(); } }
優勢:
缺點:
適用場景:
定義:
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。這樣之後就可將該對象恢復到原先保存的狀態
示例:
/** * 發起人角色 */ public class Originator { private String state; // 內部狀態 public Originator() { } public Originator(String state) { this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; } // 建立備忘錄 public Memento createMemento() { return new Memento(this.state); } // 恢復備忘錄 public void restoreMemento(Memento memento) { this.setState(memento.getState()); } public void changeState(String state) { this.setState(state); } } /** * 備忘錄 */ 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 Caretaker { private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } } /** * 測試類 */ public class MementoTest { @Test public void test() { Originator originator = new Originator("1"); System.out.println(originator.getState()); Caretaker caretaker = new Caretaker(); caretaker.setMemento(originator.createMemento()); originator.changeState("3"); System.out.println(originator.getState()); originator.restoreMemento(caretaker.getMemento()); System.out.println(originator.getState()); } }
適用場景:
定義:
封裝一些做用於某種數據結構中的各元素的操做,它能夠在不改變數據結構的前提下定義做用於這些元素的新的操做
示例:
/** * 訪問者接口 */ public interface IVisitor { void visit(ConcreteElement1 concreteElement1); void visit(ConcreteElement2 concreteElement2); } /** * 具體的訪問者 */ public class Visitor implements IVisitor { public void visit(ConcreteElement1 concreteElement1) { concreteElement1.doSomething(); } public void visit(ConcreteElement2 concreteElement2) { concreteElement2.doSomething(); } } /** * 抽象元素 */ public abstract class Element { public abstract void doSomething(); // 業務邏輯 public abstract void accept(IVisitor visitor); // 容許誰訪問 } /** * 具體元素 */ public class ConcreteElement1 extends Element { public void doSomething() { System.out.println("element1 業務邏輯"); } public void accept(IVisitor visitor) { visitor.visit(this); } } /** * 具體元素 */ public class ConcreteElement2 extends Element { public void doSomething() { System.out.println("element2 業務邏輯"); } public void accept(IVisitor visitor) { visitor.visit(this); } } /** * 結構對象 */ public class ObjectStructure { public static Element createElement() { Random random = new Random(); if(random.nextInt(100) < 50) { return new ConcreteElement1(); } else { return new ConcreteElement2(); } } } /** * 測試類 */ public class VisitorTest { @Test public void test() { for (int i = 0; i < 10; i++) { Element e = ObjectStructure.createElement(); e.accept(new Visitor()); } } }
優勢:
缺點:
適用場景:
業務規則要求遍歷多個不一樣的對象
定義:
當一個對象內在狀態改變時容許其改變行爲,這個對象看起來像改變了其類
示例:
/** * 狀態抽象類 */ public abstract class State { protected Context context; public void setContext(Context context) { this.context = context; } // 行爲1 public abstract void handle1(); // 行爲2 public abstract void hanle2(); } /** * 具體狀態 */ public class State1 extends State { public void handle1() { } public void hanle2() { super.context.setCurrentState(Context.STATE2); System.out.println("在狀態1能夠執行 handle2"); } } /** * 具體狀態 */ public class State2 extends State { public void handle1() { super.context.setCurrentState(Context.STATE1); System.out.println("在狀態2能夠執行 handle1"); } public void hanle2() { } } /** * 環境角色 */ public class Context { public static final State STATE1 = new State1(); public static final State STATE2 = new State2(); private State currentState; public State getCurrentState() { return currentState; } public void setCurrentState(State state) { this.currentState = state; this.currentState.setContext(this); } public void handle1() { this.currentState.handle1(); } public void handle2() { this.currentState.hanle2(); } } /** * 測試類 */ public class StateTest { @Test public void test() { Context context = new Context(); context.setCurrentState(new State1()); context.handle1(); context.handle2(); context.handle2(); context.handle1(); } }
優勢:
缺點:
適用場景:
定義:
使用共享對象可有效地支持大量的細粒度的對象
示例:
/** * 抽象享元角色 */ public abstract class FlyWeight { private String intrinsic; protected final String extrinsic; public FlyWeight(String extrinsic) { this.extrinsic = extrinsic; } public abstract void operate(); // 業務邏輯 public String getIntrinsic() { return intrinsic; } public void setIntrinsic(String intrinsic) { this.intrinsic = intrinsic; } } /** * 具體享元角色 */ public class ConcreteFlyWeight extends FlyWeight { public ConcreteFlyWeight(String extrinsic) { super(extrinsic); } public void operate() { System.out.println("業務邏輯"); } } /** * 享元對象工廠 */ public class FlyWeightFactory { private static HashMap<String, FlyWeight> flyWeightHashMap = new HashMap<String, FlyWeight>(); public static FlyWeight getFlyWeight(String extrinsic) { FlyWeight flyWeight = null; if (flyWeightHashMap.containsKey(extrinsic)) { flyWeight = flyWeightHashMap.get(extrinsic); } else { flyWeight = new ConcreteFlyWeight(extrinsic); flyWeightHashMap.put(extrinsic, flyWeight); } return flyWeight; } }
優勢:
能夠大大減小應用程序建立的對象,下降程序內存的佔用,加強程序的性能
缺點:
提升了系統複雜性,須要分離出外部狀態和內部狀態
適用場景:
定義:
將抽象和實現解耦,使得二者能夠獨立地變化
示例:
/** * 實現化角色 */ public interface Implementor { void doSomething(); void doAnyThing(); } /** * 具體實現化角色 */ public class ConcreteImplementor implements Implementor{ public void doSomething() { System.out.println("doSomething"); } public void doAnyThing() { System.out.println("doAnything"); } } /** * 抽象化角色 */ public abstract class Abstraction { private Implementor implementor; public Abstraction(Implementor implementor) { this.implementor = implementor; } public void request() { this.implementor.doSomething(); } public Implementor getImplementor() { return implementor; } } /** * 具體的抽象化角色 */ public class ConcreteAbstraction extends Abstraction { public ConcreteAbstraction(Implementor implementor) { super(implementor); } @Override public void request() { super.request(); super.getImplementor().doAnyThing(); } }
優勢:
適用場景: