1. 程式人生 > >工廠模式以及代理模式

工廠模式以及代理模式

工廠模式:

工廠模式是一種建立模式,:什麼是建立,我們知道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 ();





    }
}