代理模式and工廠模式之簡單插件管理器

問題:咱們老是會遇到這樣的問題---在一個複雜系統中,有一些依賴性,關聯性低的功能,好比某些場景中須要發送一個郵件。這個時候咱們須要這個「發郵件」的功能,具備低耦合的特性,只須要調用傳入參數即可實行這樣的功能。可是爲了易用性,一般會給這樣的--暫且稱爲插件的東西,加上一個開關。

代理模式:顧名思義,代理,指的是b-a-c,b須要c的功能,可是要通過a再到達c,所以在a上添加一些條件,a就變成了一個開關。舉個現實的例子,咱們的家裏都有電燈,可是咱們不但願它一直亮着,想要它亮的時候就亮,滅的時候就滅。在這裏咱們的手就是b,開關就是a,電燈就是c。

要點:面向接口編程

beginjavascript

     b-a-c這樣的過程,歸根結底是要實現c的功能,因此第一步咱們須要一個具體實現的過程java

     c(發郵件):編程

      1,定義一個發郵件的接口服務器

package plug.inter;
public interface stmp_inter{
    public boolean stmp();
}

    2,寫一個具體發郵件的功能類-stmp_imp.java,實現接口session

package plug.imp;

import plug.inter.stmp_inter;
import plug.plugControl.plugs;

import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.internet.MimeMessage.RecipientType;
import java.util.Properties;

public class stmp_imp implements stmp_inter {
    private String from;
    private String to;
    private String title;
    private String val;
    private String key;
    /*設置發送者郵箱,接受者郵箱,郵件題目,郵件服務器受權碼*/
    public stmp_imp(String from, String to, String title, String val, String key){
        this.from=from;
        this.to=to;
        this.title=title;
        this.val=val;
        this.key=key;
        stmp();
    }
    @Override
    public boolean stmp() {
        Properties properties = new Properties();
        /*連接協議*/
        properties.put("mail.transport.protocol", "smtp");
        /*服務器地址*/
        properties.put("mail.smtp.host", "smtp.qq.com");
        /*服務器端口*/
        properties.put("mail.smtp.port", 465);
        /*暫不知道*/
        properties.put("mail.smtp.auth", "true");
        /*使用ssh連接協議*/
        properties.put("mail.smtp.ssl.enable", "true");
        /*獲得回話對象*/
        Session session = Session.getInstance(properties);
        Message message = new MimeMessage(session);
        try{
            message.setFrom(new InternetAddress(from));
            message.setRecipients(RecipientType.TO,new InternetAddress[] {

                    new InternetAddress(to)
            });

            message.setSubject(title);

            message.setText(val);

            Transport transport = session.getTransport();

            transport.connect(from, key);

            transport.sendMessage(message, message.getAllRecipients());
            return true;
        }
        catch(Exception e){
            return false;
        }
    }

    @Override
    public boolean getState() {
        return false;
    }
}

   3,代理功能類,實現接口dom

package plug.imp;

import plug.inter.stmp_inter;
import plug.plugControl.plugs;

/*
* 代理模式
* 使用時上轉型
* */
public class stmp_switch implements stmp_inter{
    /*swit爲發郵件功能當前狀態,是否開啓*/
    private static boolean swit;
    private stmp_imp stm;
    private String from;
    private String to;
    private String title;
    private String val;
    private String key;
    public void stmp_set(String from, String to, String title, String val, String key){
        this.from=from;
        this.to=to;
        this.title=title;
        this.val=val;
        this.key=key;
    }
    @Override
    public boolean stmp() {
        if (stm==null&&swit){
            this.stm=new stmp_imp(from,to,title,val,key);
            stm.stmp();
            return true;
        }else{
            if(swit){
                stm.stmp();
                return true;
            }else{
                return false;
            }
        }
    }
    /*設置郵件狀態*/
    public void stmp(boolean bo){
        this.swit=bo;
    }
    public boolean getState(){
        return swit;
    }
}

   4,調試ssh

package plug.inter;

import plug.imp.stmp_switch;

public class test {
    public static void main(String[] arge){
        stmp_switch p=new stmp_switch();
        System.out.println("發郵件插件當前狀態爲"+p.getState());
        /*開啓插件*/
        p.stmp(true);
        /*設置信息*/
        p.stmp_set("510009842@qq.com","1990557780@qq.com","test","test","xxxxxxxxxx");
        /*發送郵件*/
        p.stmp();
    }
}

5,結果ide

6,由此發郵件的插件就作好了,可是這裏有兩個問題,ui

(1)咱們並不但願只使用一個插件,可是多個插件放在一塊兒就須要一個有效的管理。咱們想要裝一臺電燈,從接電線到裝開關,無疑這是一個專業的事情,這個時候咱們會去專業的電工,電工按照固定的步驟裝好電燈。一樣的咱們咱們也但願只提供材料就能直接按開關亮燈。那麼就須要引入另外一種模式-工廠模式。this

(2)咱們想要燈亮,只想要找到開關,按下開關就能夠了,可是有不少的燈,有的時候你並不知道,那個開關對應的是哪一個燈,這個時候咱們須要給開關貼上標籤。

7,定義插件工廠接口

package plug.plugControl;

public interface plugs{
    Object draw(String clsz);
}

8,配置插件信息

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <!-- 插件名-->
    <name>stmp</name>
	 <!-- 插件開關-->
    <claza>plug.imp.stmp_switch</claza>
	 <!-- 插件實現類-->
    <claza_name>stmp</claza_name>
	 <!-- 做者-->
    <admin>巫雲</admin>
	 <!-- 介紹-->
    <persent>發郵件</persent>
</root>

9,新建插件信息實體

package plug.plugControl;
/*
* plug信息
*
* */
public class bean_plug {
    private String name;
    private String claza;
    private String claza_name;
    private String admin;
    private String persent;
    private boolean state;

    public boolean isState() {
        return state;
    }

    public void setState(boolean state) {
        this.state = state;
    }

    public String getAdmin() {
        return admin;
    }

    public void setAdmin(String admin) {
        this.admin = admin;
    }

    public String getPersent() {
        return persent;
    }

    public void setPersent(String persent) {
        this.persent = persent;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getClaza() {
        return claza;
    }

    public void setClaza(String claza) {
        this.claza = claza;
    }

    public String getClaza_name() {
        return claza_name;
    }

    public void setClaza_name(String claza_name) {
        this.claza_name = claza_name;
    }
}

10,掃描配置文件

package plug.plugControl;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.util.*;
/*
* 掃描全部插件並裝載插件信息
* */
public class scans_plug{
    private static  scans_plug kl=new scans_plug();
    public static scans_plug getObj(){
        return kl;
    }
    public Object draw(HttpServletRequest request) {
        List plugzz = new LinkedList();
        String path=request.getServletContext().getRealPath("WEB-INF/classes/plug/regist");
        ArrayList<String> fileName = new ArrayList<String>();
        File files = new File(path);
        File[] filesList = files.listFiles();
        for (File file : filesList) {
            try {
                DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
                DocumentBuilder builder=factory.newDocumentBuilder();
                Document doc=builder.parse(file);
                NodeList name=doc.getElementsByTagName("name");
                NodeList claza=doc.getElementsByTagName("claza");
                NodeList claza_name=doc.getElementsByTagName("claza_name");
                NodeList admin=doc.getElementsByTagName("admin");
                NodeList persent=doc.getElementsByTagName("persent");
                bean_plug be=new bean_plug();
                be.setName(name.item(0).getFirstChild().getNodeValue());
                be.setClaza(claza.item(0).getFirstChild().getNodeValue());
                be.setClaza_name(claza_name.item(0).getFirstChild().getNodeValue());
                be.setAdmin(admin.item(0).getFirstChild().getNodeValue());
                be.setPersent(persent.item(0).getFirstChild().getNodeValue());
                plugzz.add(be);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return plugzz;
    }
}

11,偵聽插件狀態

新建狀態接口

package plug.plugControl;

public interface state_plug {
    boolean getState();
}

使開關繼承狀態接口

package plug.inter;

import plug.plugControl.plugs;
import plug.plugControl.state_plug;

public interface stmp_inter extends state_plug {
    public boolean stmp();
}

11,組建工廠核心

package plug.plugControl;

import plug.imp.stmp_switch;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/*
* 反射建立plug對象
* */
public class draw_plug implements plugs {
    @Override
    public Object draw(String clsz) {
        try {
            Class c=Class.forName(clsz);
            Constructor constructor=c.getConstructor();
            Object o=constructor.newInstance();
            return o;
        } catch (ClassNotFoundException e) {
            return null;
        } catch (NoSuchMethodException e) {
            return null;
        } catch (InstantiationException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        } catch (InvocationTargetException e) {
            return null;
        }
    }
}

12,組建工廠

package plug.plugControl;

import javax.servlet.http.HttpServletRequest;
import java.io.ObjectStreamClass;
import java.util.List;
import java.util.Map;
/**
 * 根據掃描的結果組件插件工廠
 */
public class plugFactory {
    public Object getPlug(String plug, HttpServletRequest request){
        List plugst=(List) scans_plug.getObj().draw(request);
        for(Object be:plugst ){
            bean_plug bes= (bean_plug) be;
            if(plug.equalsIgnoreCase(bes.getClaza_name())){
                state_plug c=(state_plug)new draw_plug().draw(bes.getClaza());
                bes.setState(c.getState());
                return new draw_plug().draw(bes.getClaza());
            }
        }
        return null;
    }
}

14,使用

/*
		*創建插件工廠
		*/
		plugFactory plugFactorys=new plugFactory();
		
       /* *//*
		選擇插件*//*
		stmp_switch p=(stmp_switch) plugFactorys.getPlug("STMP",request);
		*//*設置插件狀態 true/false*//*
        p.stmp(true);
		*//*設置郵件 (發件人,收件人,題目,內容,郵件受權碼)*//*
        p.stmp_set("510009842@qq.com","2235733688@qq.com","test","test","smviuilfoqdocbbf");
		*//*發送郵件*//*
        p.stmp();*/
相關文章
相關標籤/搜索