摘要:使用的主要原因是其另一個特性禁止指令重排序優化。組合能讓客戶以一致的方式處理個別對象以及對象組合。其實就是在具體類中維護一組組合模式雖然違反了單一原則,但更有價值裝飾模式動態的將責任附加到對象上。命令模式也支持撤銷操作。
創建型模式 1.工廠模式
定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法讓類吧實例化推遲到子類。
// 產品類 public interface IProduct { } public class ProductA1 implements IProduct{} public class ProductA2 implements IProduct{} public class ProductB1 implements IProduct{} public class ProductB2 implements IProduct{} // 產品枚舉類 public enum ProductEnum { A1, A2, B1, B2 } // 工廠類 public interface IFactory { IProduct create(ProductEnum productEnum); // 此處加入類型參數,只是為了更好的展示工廠方法 } // 工廠A (工廠子類--看起來是不是像簡單工廠,嘿嘿) public class FactoryA implements IFactory { public IProduct create(ProductEnum productEnum) { if(ProductEnum.A1.equals(productEnum)) { return new ProductA1(); } else if(ProductEnum.A2.equals(productEnum)) { return new ProductA2(); } return null; } } // 工廠B public class FactoryB implements IFactory { .... } // 客戶端調用 // 創建產品A1 IFactory factoryA = new FactoryA(); factoryA.create(ProductEnum.A1); // 創建產品B2 IFactory factoryB = new FactoryB(); factoryB.create(ProductEnum.B2)
簡單工廠和工廠方法的區別:簡單工廠把全部的事情在一個地方處理完了,然而工廠方法卻是創建一個框架,讓子類決定要如何實現。
// 簡單工廠 public class SimpleFactory implements IFactory { public IProduct create(ProductEnum productEnum) { switch(productEnum) { case A1: return new ProductA1(); case A2: return new ProductA2(); case B1: return new ProductB1(); case B2: return new ProductB2(); } return null; } }2.抽象工廠
提供了一個接口,用于創建相關或依賴對象的家族,而不需明確指明具體類。
// 產品家族 之 產品A public interface IProductA { } public class ProductA1 implements IProductA{} // 1號產品A public class ProductA2 implements IProductA{} // 2號產品A // 產品家族 之 產品B public interface IProductB { } public class ProductB1 implements IProductB{} // 1號產品B public class ProductB2 implements IProductB{} // 2號產品B // 工廠類 -- 注意:如果需要增加C類產品,必須改變接口 public interface IFactory { IProductA createProductA(); IProductB createProductB(); } // 工廠1: 具體工廠使用“工廠方法”來實現 public class Factory1 implements IFactory { public IProduct createProductA() { return new ProductA1; } public IProduct createProductB() { return new ProductB1; } } // 工廠2 public class Factory2 implements IFactory { .... } // 商店 public class Store { private IFactory factory; public Store(IFactory factory) { this.factory = factory; } } // 客戶端調用 // 創建1號產品 Store store1 = new Store(new Factory1()); store1.createProductA(); store1.createProductB(); // 創建2號產品 Store store2 = new Store(new Factory2()); store2.createProductA(); store2.createProductB();3.建造者模式
又稱“生成器模式”,封裝一個產品的構造過程,并允許按步驟構造。
4.單例模式StringBuilder
確保一個類只有一個實例,并提供一個全局訪問點
// 懶漢式:雙重校驗鎖 public class Singleton { private volatile static Singleton instance; private Singleton() {} public Singleton getInstance() { if(instance == null) { // Single Checked synchronized(Singleton.class) { if(instance == null) { // Double Checked return new Singleton(); } } } return instance; } }
volatile
有些人認為使用volatile的原因是可見性,也就是可以保證線程在本地不會存有 instance 的副本,每次都是去主內存中讀取。但其實是不對的。使用volatile的主要原因是其另一個特性:禁止指令重排序優化。也就是說,在volatile變量的賦值操作后面會有一個內存屏障(生成的匯編代碼上),讀操作不會被重排序到內存屏障之前。
// 靜態內部類 public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
// 餓漢式 public class Singleton{ //類加載時就初始化 private static final Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } }5.原型模式
當創建給定類的實例的過程很昂貴或很復雜時,就使用原型模式。
結構型模式 1.適配器模式Object.clone()
將一個類的接口,轉換成客戶期望的另一個接口。適配器讓原本不兼容的類可以合作無間。
/** 對象適配器 -- 比較常用 **/ public interface ITarget { void request(); } // 被適配類 public class Adaptee { public void specificRequest(){} } // 適配類:采用組合的方法 public class Adapter implements ITarget { private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } public void show() { adaptee.specificRequest(); } } // 客戶端調用 ITarget target = new ITarget(new Adaptee()); target.request();
/** 類適配器 **/ public interface ITarget { void request(); } // 被適配類 public class Adaptee { public void specificRequest(){} } // 適配類:采用繼承的方式 public class Adapter extends Adaptee implements ITarget { public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } public void show() { specificRequest(); } } // 客戶端調用 ITarget target = new ITarget(); target.request();2.橋接模式
不知改變你的實現,也改變你的抽象。
3.組合模式用于處理兩個或多個維度的變化的場景
允許你將對象組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及對象組合。
4.裝飾模式其實就是在具體類中維護一組Item
組合模式雖然違反了單一原則,但更有價值
動態的將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
// 抽象組件類 public abstract class AbsComponent { public abstract void perform(); } // 組件 public class Component extends AbsComponent { public void perform() { .... } } // 抽象裝飾者(定義此類只是為了更好的分離) public abstract class AbsDecorator extends AbsComponent { } // 裝飾者A public class DecoratorA extends AbsDecorator { AbsComponent component; // 引用組件類,用于裝飾 public DecoratorA(AbsComponent component) { this.component = component; } public void perform() { .... } } // 裝飾者A public class DecoratorB extends AbsDecorator { .... } // 客戶端調用 Component component = new Component(); DecoratorA decoratorA = new DecoratorA(component); DecoratorB decoratorB = new DecoratorB(decoratorA); decoratorB.perform();
5.外觀模式實際場景: InputStream FileInputStream...
提供一個統一的接口,用來訪問子系統的一群接口。外觀定義了一個高層接口,讓子系統更容易使用。
6.享元模式如想讓某個類的一個實例能用來提供許多“虛擬實例”,就使用享元(Flyweight)模式。
7.代理模式應用場景:緩存
為另一個對象提供一個替身或占位符以控制對這個對象的訪問。
/** 靜態代理 **/ // 被代理類 public interface ISubject { void request(); } public class RealSubject implements ISubject { public void request() {} } // 代理類 public class Proxy implements ISubject { private ISubject subject; public Proxy(ISubject subject) { this.subject = subject; } public void request() { subject.request(); } } // 客戶端調用 ISubject subject = new RealSubject(); Proxy proxy = new Proxy(subject); proxy.request();
/** JDK動態代理:被代理類必須實現接口 **/ public class MyInvocationHandler implements InvocationHandler { private Object target; public DyProxy(Object target) { this.target = target; } @override public Object invoke(Object proxy, Method method, Object[] args) throw Throwable { // 此處可添加前置條件 Object result = method.invoke(target, args); // 此處可添加后置條件 return result; } // 獲取代理對象 public Object getProxy() { ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class>[] infs = target.getClass().getInterfaces(); return Proxy.newProxyInstance(loader, infs, this); } } // 客戶端調用 ISubject subject = new RealSubject(); MyInvocationHandler handler = new MyInvocationHandler(serive); ISubject subjectProxy = (ISubject)handler.getProxy(); subjectProxy.request();
行為型模式 1.責任鏈模式JDK動態代理只能對實現了接口的類生成代理,而不能針對類
CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法(又稱織入)
當你想要讓一個以上的對象有機會能夠處理某個請求的時候,就是用責任鏈模式。
2.命令模式FilterChain
游戲: 擊鼓傳花
將“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。命令模式也支持撤銷操作。
// 命令 public interface ICommand { void exec(); void undo(); } // 接收者 public class Receiver { public void action() { .... } } // 命令實現類 public class CommandImpl { private Receiver receiver; public CommandImpl() { this.receiver = receiver; } public void exec() { receiver.action(); } ... } // 調用者 public class Invoker { private ICommand command; public void setCommand(ICommand command) { this.command = command; } public void exec() { command.exec(); } } // 客戶端調用 ICommand command = new CommandImpl(new Receiver()); Invoker invoker = new Invoker(); invoker.setCommand(command); invoker.exec();
3.解釋器模式應用場景:隊列請求、日志請求
為語言創建解釋器
4.迭代器模式沒用過也沒想用過...
提供一個方法順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。
5.中介者模式Iterator
集中對象之間復雜的溝通和控制方式。
6.備忘錄模式舉個栗子:CPU調度
讓對象返回之前的狀態(例如:撤銷)。
7.觀察者模式說白了,就是在內部維護一個state
定義了對象之間的一對多依賴,這樣一來,當一個對象改變狀態時,它的所有依賴著都會收到通知并自動更新。
// 觀察者接口 public interface IObserver { void update(); } // 觀察者A public class ObserverA implements IObserver { .... } // 觀察者B public class ObserverB implements IObserver { .... } // 主題接口 public interface ISubject { void register(IObserver observer); void remove(IObserver observer); void notifyObservers(); } // 主題實現類 public class SubjectImpl implements ISubject { private Listobservers; public SubjectImpl() { observers = new ArrayList<>(); } public void register(IObserver observer) { observers.add(observer); } public void remove(IObserver observer) { observers.remove(observer); } public void notifyObservers() { for(IObserver observer : observers) { observer.update(); } } } // 客戶端調用 ISubject subject = new SubjectImpl(); subject.register(new ObserverA()); subject.register(new ObserverB()); subject.notifyObservers();
/** JDK內置的觀察者模式:通過繼承Observable實現通知 **/ // 觀察者 public interface Observer { void update(Observable o, Object arg); } // 主題 public class Observable { private boolean changed = false; private Vector obs; public synchronized void addObserver(Observer o) { .... obs.addElement(o); } public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } public void notifyObservers(Object arg) { .... ((Observer)arrLocal[i]).update(this, arg); .... } // 多了一個setChange方法,用于保證當達到臨界條件時,才會通知,而不 // 是只要改變就通知 protected synchronized void setChanged() { changed = true; } }8.策略模式
定義了算法家族,分別封裝起來,讓它們之間可以相互替換,此模式讓算法的變化獨立于使用算法的客戶。
// 策略接口 public interface IStrage { void opreate(); } // 具體策略類 public class StrageA implements IStrage { .... } public class StrageB implements IStrage { .... } // 上下文 public class Context { private IStrage strage; public void setStrage(IStrage strage) { this.strage = strage; } public void opreate() { strage.opreate(); } } // 客戶端調用 IStrage strage = new StrageA(); Context ctx = new Context(); ctx.setStrage(strage); ctx.opreate();
9.狀態模式應用場景:session策略
允許對象在內部狀態改變時改變它的行為,對象看起來好像修改了它的類。
// 狀態接口 public interface IState { void handle(); } // 具體狀態類A public class StateA implements IState { private Context ctx; public StateA(Context ctx) { this.ctx = ctx; } public void handle() { // 可以直接處理 .... // 也可以轉移狀態 ctx.setState(ctx.getStateB()); } } // 具體狀態類B public class StateB implements IState { .... } // 上下文 public class Context { private IState stateA; private IState stateB; private IState state = stateA; // 默認狀態A public Context() { stateA = new StateA(this); stateB = new StateB(this); } public void setState(IState state) { this.state = state; } public void setStateA(IState stateA) { this.stateA = stateA; } public void setStateB(IState stateB) { this.stateB = stateB; } public void opreate() { state.handle(); } ... } // 客戶端調用 Context ctx = new Context(); ctx.opreate(); // 狀態A -> 轉移到B狀態 ctx.opreate(); // 狀態B
10.模版方法是不是和策略模式很像?
以狀態模式而言,我們將一群行為封裝在狀態對象中,context的行為隨時可以委托到那些對象中的一個。隨著時間的流逝,當前狀態在狀態對象集合中游走改變。但是context的客戶對于狀態對象了解不多,甚至根本是渾然不覺。
而以策略模式而言,客戶通常注定指定Context所要組合的策略對象是哪一個。現在,固然策略模式讓我們更具有彈性,能夠在運行時改變策略,但對于某個context對象來說,通常都只有一個最適當的策略對象。
在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模版方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。
11.訪問者模式其實就是使用抽象類
設計原則見名知義,最簡單的體現就是setter/getter方法
封裝變化
針對接口編程,不針對實現編程
多用組合,少用繼承
為交互對象之間的松耦合設計而努力
開放-關閉原則:類應該對擴展開放,對修改關閉
依賴倒置原則:依賴抽象,不要依賴具體類
最少知識原則:減少對象之間的交互
好萊塢原則:讓低層組件掛鉤進計算中,而又不會讓高層組件依賴低層組件
單一原則:一個類應該只有一個引起變化的原因
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67494.html
摘要:目前類似的工具有,等。在渲染進程中,直接調用原生的接口是十分危險的。這里介紹一種,通過和對象,以消息的方式進行通信。主進程獲得消息后,通過返回信息。另外,還提供了一種同步的消息傳遞方式。打包完成功能代碼后,我們需要將代碼打成可運行的包。 介紹 目前,使用前端技術開發桌面應用已經越來越成熟,這使得前端同學也可以參與桌面應用的開發。目前類似的工具有electron,NW.js等。這里我們著...
摘要:本周精讀內容是逃離地獄。精讀仔細思考為什么會被濫用,筆者認為是它的功能比較反直覺導致的。同時,筆者認為,也不要過渡利用新特性修復新特性帶來的問題,這樣反而導致代碼可讀性下降。 本周精讀內容是 《逃離 async/await 地獄》。 1 引言 終于,async/await 也被吐槽了。Aditya Agarwal 認為 async/await 語法讓我們陷入了新的麻煩之中。 其實,筆者...
摘要:現在回過頭總結,才又進一步的揭開了閉包的一層后臺管理系統解決方案前端掘金基于系列的后臺管理系統解決方案。什么是繼承大多數人使用繼承不外乎是為了獲得基于的單頁應用項目模板前端掘金小貼士本項目已升級至。 關于js、jq零碎知識點 - 掘金寫在前面: 本文都是我目前學到的一些比較零碎的知識點,也是相對偏一點的知識,這是第二篇。前后可能沒有太大的相關性,需要的朋友可以過來參考下,喜歡的可以點個...
摘要:無論如何,單元測試一直是一中非常重要卻常常被忽視的技能。在實踐中,重構的要求是很高的它需要有足夠詳盡的單元測試,需要有持續集成的環境,需要隨時隨地在小步伐地永遠讓代碼處于可工作狀態下去進行改善。 showImg(https://segmentfault.com/img/bVbttWF?w=1000&h=528); 五月初的時候朋友和我說《重構》出第 2 版了,我才興沖沖地下單,花了一個...
摘要:要寫出一個健壯的程序必須要有測試,測試可以保證上線的代碼功能符合預期,防止上線后出現莫須有的損失。根據這樣的想法,于是編寫了一個測試框架。的使用非常簡單,你只需要把你的測試案例信息寫成固定的格式,包括請求信息,預期響應信息,預期的數據信息。 要寫出一個健壯的程序必須要有測試,測試可以保證上線的代碼功能符合預期,防止上線后出現莫須有的損失。對于我們一口氣寫完的api,匆忙上線往往會導致很...
閱讀 1818·2021-11-18 13:21
閱讀 1953·2021-10-18 13:30
閱讀 1539·2021-10-12 10:13
閱讀 906·2021-10-09 09:43
閱讀 5413·2021-09-22 15:13
閱讀 3583·2021-08-11 10:22
閱讀 936·2019-08-30 13:46
閱讀 3520·2019-08-30 13:21