代理模式and工厂模式之简单插件管理器

问题:我们总是会遇到这样的问题---在一个复杂系统中,有一些依赖性,关联性低的功能,比如某些场景中需要发送一个邮件。这个时候我们需要这个“发邮件”的功能,具有低耦合的特性,只需要调用传入参数便可实行这样的功能。但是为了易用性,通常会给这样的--暂且称为插件的东西,加上一个开关。
代理模式:顾名思义,代理,指的是b-a-c,b需要c的功能,但是要经过a再到达c,因此在a上添加一些条件,a就变成了一个开关。举个现实的例子,我们的家里都有电灯,但是我们不希望它一直亮着,想要它亮的时候就亮,灭的时候就灭。在这里我们的手就是b,开关就是a,电灯就是c。
要点:面向接口编程

begin

     b-a-c这样的过程,归根结底是要实现c的功能,所以第一步我们需要一个具体实现的过程

     c(发邮件):

      1,定义一个发邮件的接口

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

    2,写一个具体发邮件的功能类-stmp_imp.java,实现接口

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,代理功能类,实现接口

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,调试

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,结果

6,由此发邮件的插件就做好了,但是这里有两个问题,

(1)我们并不希望只使用一个插件,但是多个插件放在一起就需要一个有效的管理。我们想要装一台电灯,从接电线到装开关,无疑这是一个专业的事情,这个时候我们会去专业的电工,电工按照固定的步骤装好电灯。同样的我们我们也希望只提供材料就能直接按开关亮灯。那么就需要引入另一种模式-工厂模式。

(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();*/

 

转载于:https://my.oschina.net/u/3188070/blog/1857658

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值