工廠模式:
工廠模式是一種創建模式,:什么是創建,我們知道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 class Apple 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 (); } }