工廠模式以及代理模式
工廠模式:
工廠模式是一種建立模式,:什麼是建立,我們知道Java是面向物件的語言,那麼我們想使用類中的方法以及屬性,那麼我們需要建立物件才能呼叫,那麼我們我們必須:A a = new A();來建立例項,我們的工廠模式就是使用工廠來幫我們建立物件。工廠模式主要是為建立物件提供了介面:工廠模式分為3類:簡單工廠 、工廠方法、抽象工廠、工廠模式我們在什麼時候使用呢?
1.在編碼時不能預見需要建立那種物件。
2.系統不應依賴於產品類例項如何被建立,組合、和表達的細節。
一、簡單工廠模式:
這個模式很簡單,使用的業務比較簡單的情況下;
由3種角色組成:
工廠類角色::這是本模式的核心,含有一定的商業邏輯和判斷邏輯。在java中它往往由一個具體類實現
抽象產品角色:它一般是具體產品繼承的父類或者實現的介面。在java中由介面或者抽象類來實現
具體產品角色:工廠類所建立的物件就是此角色的例項。在java中由一個具體類實現
package com.factory.simple; /** * 水果介面 */ public interface Fruitable { // 水果的功能 void WhatIm(); }
package com.factory.simple; /** * @author :wuzhilong * @date:2018年10月25日 */ public classApple implements Fruitable { @Override public void WhatIm() { } }
package com.factory.simple; /** * @author :wuzhilong * @date:2018年10月25日 */ public class FruitFactory { //工廠方法 public Fruitable createFruit(String type){ if("apploe".equals (type)){return new Apple (); }else if("Pear".equals (type)){ return new Pear (); } return null; } }
工廠方法模式:
1、抽象工廠角色:這是工廠方法模式的核心,它與應用程式無關。是具體工廠角色必須實現的介面或者必須繼承的父類。在java中它由抽象類或者介面來實現。
2、具體工廠角色:它含有和具體業務邏輯有關的程式碼。由應用程式呼叫以建立對應的具體產品的物件。在java中它由具體的類來實現。
3、抽象產品角色:它是具體產品繼承的父類或者是實現的介面。在java中一般有抽象類或者介面來實現。
4、具體產品角色:具體工廠角色所建立的物件就是此角色的例項。在java中由具體的類來實現。
package com.factory.method; /** * 工廠介面 */ public interface FactoryInterface { Fruit createFruit(); }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 * 每個產品的具體工廠 */ public class AppleFactory implements FactoryInterface { @Override public Fruit createFruit() { return new Apple (); } }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 * 每個產品的具體工廠 */ public class PearFactory implements FactoryInterface { @Override public Fruit createFruit() { return new Pear (); } }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 * 水果類 */ public abstract class Fruit { }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 */ public class Apple extends Fruit { }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 */ public class Pear extends Fruit { }
抽象工廠模式:
1.系統中有多個產品族,而系統一次只可能消費其中一族產品
2.同屬於同一個產品族的產品一起使用時。
來看看抽象工廠模式的各個角色(和工廠方法的如出一轍):
抽象工廠角色:這是工廠方法模式的核心,它與應用程式無關。是具體工廠角色必須實現的介面或者必須繼承的父類。在java中它由抽象類或者介面來實現。
具體工廠角色:它含有和具體業務邏輯有關的程式碼。由應用程式呼叫以建立對應的具體產品的物件。在java中它由具體的類來實現。
抽象產品角色:它是具體產品繼承的父類或者是實現的介面。在java中一般有抽象類或者介面來實現。
具體產品角色:具體工廠角色所建立的物件就是此角色的例項。在java中由具體的類來實現。
package com.factory.abs; /** * 產品介面 */ public interface ThinkPadInterface { public void show(); }
package com.factory.abs; /** * @author :wuzhilong * @date:2018年10月25日 * 具體的產品 */ public class ThinkPadE implements ThinkPadInterface { @Override public void show() { } }
package com.factory.abs; /** * @author :wuzhilong * @date:2018年10月25日 * 具體的產品 */ public class ThinkPadT implements ThinkPadInterface { @Override public void show() { } }
package com.factory.abs; /** * 工廠介面 */ public interface FactoryInterface { public ThinkPadE createThinkPad(); public ThinkPadT createThinkPadE(); }
package com.factory.abs; /** * @author :wuzhilong * @date:2018年10月25日 * 工廠 */ public class Factory implements FactoryInterface{ @Override public ThinkPadE createThinkPad() { return new ThinkPadE (); } @Override public ThinkPadT createThinkPadE() { return new ThinkPadT (); } }
代理模式:
什麼是代理模式:
Proxy模式又叫代理模式,是構造型的模式之一,它可以為其他物件提供一種代理(Proxy)以控制對這個物件的訪問。
所謂代理,是指具有與代理元(被代理的物件)具有相同的介面的類,客戶端必須通過代理與被代理的目標類互動,而代理一般在互動的過程中(互動前後)進行某些特別的處理。
代理模式結構圖:
代理模式的實現
代理模式可以有兩種實現的方式,一種是靜態代理類,另一種是各大框架都喜歡的動態代理
靜態代理:
package com.wuzhilong.proxy; public interface ISinger { public void sing(); }
package com.wuzhilong.proxy; /** * 目標物件實現某一介面 */ public class Singer implements ISinger{ public void sing(){ System.out.println ("唱一首歌......"); } }
package com.wuzhilong.proxy; /** * 代理物件和目標物件實現相同介面 */ public class SingerProxy implements ISinger { //接收目標物件,來呼叫sing方法 private ISinger singer; public SingerProxy(ISinger singer) { this.singer = singer; } //對目標物件的sing方法進行擴充套件 @Override public void sing() { System.out.println ("向觀眾問好"); singer.sing (); System.out.println ("謝謝大家"); } }
測試:
package com.wuzhilong.proxy; /** * 靜態代理模式 */ public class Demo { public static void main(String[] args) { //目標物件 ISinger iSinger = new Singer (); //代理物件 ISinger iSinger1 = new SingerProxy (iSinger); iSinger1.sing (); } }
總結:其實這裡做的事情無非就是,建立一個代理類SingerProxy,繼承了ISinger介面並實現了其中的方法。只不過這種實現特意包含了目標物件的方法,正是這種特徵使得看起來像是“擴充套件”了目標物件的方法。假使代理物件中只是簡單地對sing方法做了另一種實現而沒有包含目標物件的方法,也就不能算作代理模式了。所以這裡的包含是關鍵。
缺點:這種實現方式很直觀也很簡單,但其缺點是代理物件必須提前寫出,如果介面層發生了變化,代理物件的程式碼也要進行維護。如果能在執行時動態地寫出代理物件,不但減少了一大批代理類的程式碼,也少了不斷維護的煩惱,不過執行時的效率必定受到影響。這種方式就是接下來的動態代理。
動態代理(JDK代理):
package com.wuzhilong.jdkproxy; public interface ISinger { public void sing(); }
package com.wuzhilong.jdkproxy; import com.wuzhilong.jdkproxy.ISinger; /** * 目標物件實現某一介面 */ public class Singer implements ISinger { public void sing(){ System.out.println ("唱一首歌......"); } }
package com.wuzhilong.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class SingerProxy implements InvocationHandler { //需要代理的真實物件 private Object subject; // 構造方法,給我們要代理的真實物件賦初值 public SingerProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println ("向觀眾問好"); // 執行目標類的方法 method.invoke (subject,args); System.out.println ("謝謝大家"); return null; } }
package com.wuzhilong.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Demo { public static void main(String[] args) throws Exception{ //代理的真實物件 ISinger singer = new Singer (); // 我們要代理哪個真實物件,就將該物件傳進去,最後是通過該真實物件來呼叫其方法的 InvocationHandler invocationHandler = new SingerProxy (singer); /* * 通過Proxy的newProxyInstance方法來建立我們的代理物件,我們來看看其三個引數 * 第一個引數 handler.getClass().getClassLoader() ,我們這裡使用handler這個類的ClassLoader物件來載入我們的代理物件 * 第二個引數realSubject.getClass().getInterfaces(),我們這裡為代理物件提供的介面是真實物件所實行的介面,表示我要代理的是該真實物件,這樣我就能呼叫這組介面中的方法了 * 第三個引數handler, 我們這裡將這個代理物件關聯到了上方的 InvocationHandler 這個物件上 */ ISinger singerProxy =(ISinger) Proxy.newProxyInstance (invocationHandler.getClass ().getClassLoader (),singer.getClass ().getInterfaces (),invocationHandler); //通過代理物件執行方法 singerProxy.sing (); } }