控制反转(Inversion of Control)大大降低了代码的耦合性。实例是由容器注入到对象中,而不是主动创建的。
IoC将对象生成放置在配置文件中,只需要修改配置文件就可以更换实现类。
实现简单的IOC
public interface Action { public String execute(String str); } public class UpperAction implements Action { private String message; public String getMessage() { return message; } public void setMessage(String string) { message = string; } public String execute(String str) { return (getMessage() + str).toUpperCase(); } } public class LowerAction implements Action { private String message; public String getMessage() { return message; } public void setMessage(String string) { message = string; } public String execute(String str) { return (getMessage() + str).toLowerCase(); } }
public class ActionFactory { public static Action getAction(String actionName) { Properties prop = new Properties(); try { ClassLoader loader = ActionFactory.class.getClassLoader(); prop.load(loader.getResourceAsStream("config.properties")); String actionImplName = (String) prop.get(actionName); String actionMessage = (String) prop.get(actionName + "_msg"); Class cl = Class.forName(actionImplName); Object obj = cl.newInstance(); // 反射机制获取域参数并为域参数值注入值 Field[] fields = cl.getDeclaredFields(); Field field = fields[0]; String fieldName = field.getName(); String firstLetter = fieldName.substring(0, 1).toUpperCase(); String setMethodName = "set" + firstLetter + fieldName.substring(1); Method setMethod = cl.getMethod(setMethodName, new Class[] { field.getType() }); setMethod.invoke(obj, new Object[] { actionMessage }); return (Action) obj; } catch (Exception e) { e.printStackTrace(); } return null; } }
config.properties配置文件:
TheAction=test.UpperAction
TheAction_msg=Hello
public class TestAction { public static void main(String[] args) { Action action = ActionFactory.getAction("TheAction"); System.out.println(action.execute(“ World ")); } }
输出结果:
HELLO WORLD
设计模式—代理模式
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户端不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理的常见应用就是对遗留系统的封装。
代理模式一般涉及到的角色有
抽象角色:声明真实对象和代理对象的共同接口
代理角色:代理对象角色一般内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装
真实角色:代理角色所代表的真实对象,是最终要引用的对象
代理模式-原理图
代理类和被代理类均派生自同一个接口,被代理类对象作为代理类构造函数参数的方式将代理权交出,代理类有接口中定义的方法,还有其他事务处理方法。
代理模式-时序图
代理模式-例子
public interface UserDAO { public void saveUser(User user); }
public class UserDAOImpl implements UserDAO { @Override public void saveUser(User user) { System.out.println("save a user," + "Id:" + user.getId() + ",Name:" + user.getName()); } }
public class UserDAOProxy implements UserDAO { private UserDAO userDAO; public UserDAOProxy(UserDAO userDAO) { this.userDAO = userDAO; } @Override public void saveUser(User user) { startTransaction(); userDAO.saveUser(user); endTransaction(); } private void startTransaction() { System.out.println("start transaction."); } private void endTransaction() { System.out.println("end transaction."); } }
public class User { private Integer id; private String name; public User(Integer id, String name) { super(); this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Test { public static void main(String[] args) { UserDAO userDAO = new UserDAOProxy(new UserDAOImpl()); userDAO.saveUser(new User(1, "Peter")); } }
输出:
start transaction.
save a user,Id:1,Name:Peter
end transaction.
由以上代码可以看出,客户实际需要调用的是UserDAOImpl类的saveUser()方法,现在用UserDAOProxy来代理UserDAOImp类,同样达到目的,同时还进行了事务的处理,当然还可以处理一些其他问题,如安全、日志等。
另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。(待续)