代理模式的核心其实就是在 上层代码和framework层代码之间增加一个中间层。
从而对于核心代码来说,对于上层是透明的。
使用代理模式可以很好的,剪切核心代码功能,或者扩展功能已符合上层代码的使用。
已一个开关camera的例子来演示代理模式:
1.对于上层来说,并不关心camera的类型,焦距之类的,只要有开关就可以了。
2.对于具体的camera类来说,它有很多功能可以设置。
UML图:
camera操作接口:
public interface ICameraOperator { boolean open(); void close(); }
camera抽象实现类:
public abstract class BasicCamera { private String name = null; public BasicCamera(String name) { this.name = name; } public boolean open() { System.out.println(name+" camera"+" open"); return true; } public void close() { System.out.println(name+" camera"+" close"); } }
所有camera都实现上述类,而代理只需要调用BasicCamera 的open和close就可以实现对实际camera的操作。
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class ProxyCamera implements ICameraOperator { private static final String AssemblyName = "com.jayfulmath.designpattern.proxy"; private static final String DefaultCamera = "YUUCamera"; private String CameraString = null; BasicCamera camera = null; private static ProxyCamera _mInstance = null; public static ProxyCamera getInstance() { if(_mInstance == null) { _mInstance = new ProxyCamera(); } return _mInstance; } public ProxyCamera() { IXmlParse parse = new XmlParse("src/com/jayfulmath/designpattern/proxy/CameraConfig.xml"); CameraString = parse.parseXmlValue("camera"); if(CameraString == null) { CameraString = DefaultCamera; } String className = AssemblyName + "." + CameraString; Class<?> c; try { c = Class.forName(className); Constructor<?> ct = c.getConstructor(); camera = (BasicCamera) (ct.newInstance()); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public boolean open() { boolean result = false; if (camera != null) { result = camera.open(); } return result; } @Override public void close() { if (camera != null) { camera.close(); } } }
此处camera的配置用到了反射和xml配置文件,从而,我们只需要在xml里面配置具体的camera就可以实现对camera使用的切换,
而上层则根本不需要知道调用哪个camera.
import java.io.File; import java.io.IOException; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class XmlParse implements IXmlParse { private String xmlPath = null; DocumentBuilderFactory builderFactory = DocumentBuilderFactory .newInstance(); public HashMap<String, String> mNode = new HashMap(); public XmlParse(String path) { xmlPath = path; mNode.clear(); init(); } public void init() { Document doc = parse(xmlPath); Element rootElement = doc.getDocumentElement(); // traverse child elements NodeList nodes = rootElement.getElementsByTagName("key"); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element child = (Element) node; if(child.getAttribute("name") != null) { mNode.put(child.getAttribute("name"), child.getTextContent()); } } } } // Load and parse XML file into DOM public Document parse(String filePath) { Document document = null; try { // DOM parser instance DocumentBuilder builder = builderFactory.newDocumentBuilder(); // parse an XML file into a DOM tree document = builder.parse(new File(filePath)); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return document; } @Override public String parseXmlValue(String name) { String result = null; if(mNode!=null && mNode.size()>0) { if(mNode.containsKey(name)) { result = mNode.get(name); } } return result; } }
public interface IXmlParse { String parseXmlValue(String name); }
xml 解析和解析接口。
最后就是main方法:
package com.jayfulmath.designpattern.proxy; import com.jayfulmath.designpattern.main.BasicExample; public class ProxyMain extends BasicExample { @Override public void startDemo() { ProxyCamera mCamera = ProxyCamera.getInstance(); mCamera.open(); mCamera.close(); } }
代理模式主要目的就是通过代理,而使实际下层操作类对上层界面的透明。并且proxy可以根据情况适当的裁剪和扩展实际下层camera的操作。