面试题—设计模式篇
一、單例模式
- 懶漢模式
- 餓漢模式
二、原型模式
class Prototype implements Cloneable {public Prototype clone(){Prototype prototype = null;try{prototype = (Prototype)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return prototype; } }class ConcretePrototype extends Prototype{public void show(){System.out.println("原型模式實現類");} }public class Client {public static void main(String[] args){ConcretePrototype cp = new ConcretePrototype();for(int i=0; i< 10; i++){ConcretePrototype clonecp = (ConcretePrototype)cp.clone();clonecp.show();}} }原型模式主要用于對象的復制,它的核心是就是類圖中的原型類Prototype。Prototype類需要具備以下兩個條件:
- 實現Cloneable接口。在java語言有一個Cloneable接口,它的作用只有一個,就是在運行時通知虛擬機可以安全地在實現了此接口的類上使用clone方法。在java虛擬機中,只有實現了這個接口的類才可以被拷貝,否則在運行時會拋出CloneNotSupportedException異常。
- 重寫Object類中的clone方法。Java中,所有類的父類都是Object類,Object類中有一個clone方法,作用是返回對象的一個拷貝,但是其作用域protected類型的,一般的類無法調用,因此,Prototype類需要將clone方法的作用域修改為public類型。
- 原型模式是一種比較簡單的模式,也非常容易理解,實現一個接口,重寫一個方法即完成了原型模式。在實際應用中,原型模式很少單獨出現。經常與其他模式混用,他的原型類Prototype也常用抽象類來替代。
三、代理模式
1)代理模式的好處
- 中介隔離作用:在某些情況下,一個客戶類不想或者不能直接引用一個委托對象,而代理類對象可以在客戶類和委托對象之間起到中介的作用,其特征是代理類和委托類實現相同的接口。
- 開閉原則,增加功能:代理類除了是客戶類和委托類的中介之外,我們還可以通過給代理類增加額外的功能來擴展委托類的功能,這樣做我們只需要修改代理類而不需要再修改委托類,符合代碼設計的開閉原則。代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事后對返回結果的處理等。代理類本身并不真正實現服務,而是同過調用委托類的相關方法,來提供特定的服務。真正的業務功能還是由委托類來實現,但是可以在業務功能執行的前后加入一些公共的服務。例如我們想給項目加入緩存、日志這些功能,我們就可以使用代理類來完成,而沒必要打開已經封裝好的委托類。
2)靜態代理
//第一步:創建服務類接口 public interface BuyHouse {void buyHosue(); }//第二步:實現服務接口 import main.java.proxy.BuyHouse; public class BuyHouseImpl implements BuyHouse {@Overridepublic void buyHosue() {System.out.println("我要買房");} }//第三步:創建代理類 package main.java.proxy.impl; import main.java.proxy.BuyHouse; public class BuyHouseProxy implements BuyHouse {private BuyHouse buyHouse;public BuyHouseProxy(final BuyHouse buyHouse) {this.buyHouse = buyHouse;}@Overridepublic void buyHosue() {System.out.println("買房前準備");buyHouse.buyHosue();System.out.println("買房后裝修");} }//第四步:編寫測試類 import main.java.proxy.impl.BuyHouseImpl; import main.java.proxy.impl.BuyHouseProxy; public class ProxyTest {public static void main(String[] args) {BuyHouse buyHouse = new BuyHouseImpl();buyHouse.buyHosue();BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);buyHouseProxy.buyHosue();} }靜態代理總結:
- 優點:可以做到在符合開閉原則的情況下對目標對象進行功能擴展。
- 缺點:我們得為每一個服務都得創建代理類,工作量太大,不易管理。同時接口一旦發生改變,代理類也得相應修改
3)動態代理
在動態代理中我們不再需要再手動的創建代理類,我們只需要編寫一個動態處理器就可以了。真正的代理對象由JDK再運行時為我們動態的來創建。
//第一步:編寫動態處理器 package main.java.proxy.impl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynamicProxyHandler implements InvocationHandler {private Object object;public DynamicProxyHandler(final Object object) {this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("買房前準備");Object result = method.invoke(object, args);System.out.println("買房后裝修");return result;} }//第二步:編寫測試類 package main.java.proxy.test; import main.java.proxy.BuyHouse; import main.java.proxy.impl.BuyHouseImpl; import main.java.proxy.impl.DynamicProxyHandler; import java.lang.reflect.Proxy; public class DynamicProxyTest {public static void main(String[] args) {BuyHouse buyHouse = new BuyHouseImpl();BuyHouse proxyBuyHouse = (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader(), newClass[]{BuyHouse.class}, new DynamicProxyHandler(buyHouse));proxyBuyHouse.buyHosue();} }四、工廠模式
1、工廠模式是什么
- ?工廠模式的定義:是創建模式的一種,共分為簡單工廠,工廠方法和抽象工廠三種
2、使用工廠模式的好處是什么?
- 解耦:把對象的創建和使用的過程分開。就是Class A 想調用 Class B ,那么A只是調用B的方法,而至于B的實例化,就交給工廠類。
- 降低代碼重復:如果創建對象B的過程都很復雜,需要一定的代碼量,而且很多地方都要用到,那么就會有很多的重復代碼。我們可以這些創建對象B的代碼放到工廠里統一管理。既減少了重復代碼,也方便以后對B的創建過程的修改維護。(當然,我個人覺得也可以把這些創建過程的代碼放到類的構造函數里,同樣可以降低重復率,而且構造函數本身的作用也是初始化對象。不過,這樣也會導致構造函數過于復雜,做的事太多,不符合java 的設計原則。)
- 減少修改量:由于創建過程都由工廠統一管理,所以發生業務邏輯變化,不需要找到所有需要創建B的地方去逐個修正,只需要在工廠里修改即可,降低維護成本。同理,想把所有調用B的地方改成B的子類B1,只需要在對應生產B的工廠中或者工廠的方法中修改其生產的對象為B1即可,而不需要找到所有的new B()改為new B1()。
- 減少使用復雜度:另外,因為工廠管理了對象的創建邏輯,使用者并不需要知道具體的創建過程,只管使用即可,減少了使用者因為創建邏輯導致的錯誤。
3、工廠模式的具體分類及實現代碼
- 產品類代碼如下:
- 1)簡單工廠
- 2)工廠方法
3、簡單工廠與工廠方法的區別是什么?
- 簡單工廠所有產品由同一個工廠創建
- 工廠方法每一個產品對應一個工廠
?
總結
- 上一篇: java.lang包—类Class应用之
- 下一篇: 双指针算法基本原理和实践