《Head First设计模式》阅读笔记.第十一章

1、代理(Proxy)模式部分

实现RMI(远程方法调用)的步骤:
引用
---------------------------------------------------------------
一、定义远程服务接口,扩展java.rmi.Remote。
二、实现远程服务具体类,继承java.rmi.UnicastRemoteObject类。
三、利用rmic生成Stub和Skeleton类,在JDK5.0中使用了动态代理,不需要生成任何类。
四、启动RMI注册表(rmiregistry)。
五、启动远程服务,即将远程服务具体类注册到RMI注册表中。
六、调用远程服务。
---------------------------------------------------------------


使用RMI常犯的三个错误:
引用
---------------------------------------------------------------
一、忘了在启动远程服务之前先启动RMI注册表(要用Naming.rebind()注册服务,rmiregistry必须是运行的)。
二、忘了将变量和返回值的类型转为可序列化的类型(这种错误无法在编译期发现,只会在运行时发现)。
三、忘了给客户端提供Stub类。
---------------------------------------------------------------


*transient关键字可以让JVM在序列化对象时忽略这个变量。

代理模式:为另一个对象提供替身或占位符以控制对这个对象的访问。

*使用代理模式创建代表(Representative)对象,让代表对象控制某对象的访问。被代理的对象可以是远程对象、创建开销大的对象或者需要安全控制的对象。

*远程代理是一般代理模式的一种实现。

代理模式有很多变种,几乎都与控制访问有关,它控制访问的几种方式:
引用
---------------------------------------------------------------
一、远程代理控制远程对象的访问。
二、虚拟代理控制创建开销大的资源的访问。
三、保护代理基于权限控制对资源的访问。
---------------------------------------------------------------


*远程代理(Remote Proxy)模式:可以作为另一个JVM上对象的本地代表。调用代理的方法会被代理利用网络转发到远程执行,并且结果会通过网络返回给代理,再由代理将结果转给客户。

*虚拟代理(Virtual Proxy)模式:作为创建开销大的对象的代表。虚拟代理经常在我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由代理来扮演它的替身。对象创建后,代理就会将请求直接委托给对象。

设计谜题
---------------------------------------------------------------
使用第十章的状态(State)模式对ImageProxy类进行重新设计。
---------------------------------------------------------------

*动态代理:Java在java.lang.reflect包中有自己的代理支持。利用这个包你可以在运行时动态地创建代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。因为实际的代理类是在运行时创建的,因此称这项Java技术为动态代理。

NonOwnerInvocationHandler代码:
---------------------------------------------------------------
import java.lang.reflect.*;

public class NonOwnerInvocationHandler implements InvocationHandler {
  PersonBean person;
  
  public NonOwnerInvocationHandler(PersonBean person){
    this.person = person;
  }
  
  public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException{
    try{
      if(method.getName().startsWith("get")){
        return method.invoke(person,args);
      }else if(method.getName().equals("setHotOrNotRating")){
        return method.invoke(person,args);
      }else if(method.getName().startsWith("set")){
        throw new IllegalAccessException();
      }
    } catch (InvocationTargetException e){
      e.printStackTrace();
    }
    return null;
  }
}
---------------------------------------------------------------


Sharpen your pencil解答:
---------------------------------------------------------------
PersonBean getNonOwnerProxy(PersonBean person){
  return (PersonBean)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new NonOwnerInvocationHandler());
}

PersonBean getProxy(PersonBean person,InvocationHandler handler){
  if(handler instanceof OwnerInvocationHandler){
    return getOwnerProxy(person);
  }else if(handler instanceof NonOwnerInvocationHandler){
    return getNonOwnerProxy(person);
  }
}
---------------------------------------------------------------


连连看解答:
引用
---------------------------------------------------------------
装饰者(Decorator)模式-->包装另一个对象,并提供额外的行为。
外观(Facade)模式-->包装许多对象以简化它们的接口。
代理(Proxy)模式-->包装另一个对象,并控制对它的访问。
适配器(Adapter)模式-->包装另一个对象,并提供不同的接口。
---------------------------------------------------------------


其他种类的代理:
引用
---------------------------------------------------------------
一、防火墙代理(Firewall Proxy):控制网络资源的访问,保护资源免受“坏客户”的侵害。
二、只能引用代理(Smart Reference Proxy):当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
三、缓存代理(Caching Proxy):为开销大的计算结果提供暂时存储。它允许多个客户共享结果以减少计算或网络延迟。
四、同步代理(Synchronization Proxy):在多线程的情况下为主题提供安全的访问。
五、复杂隐藏代理(Complexity Hiding Proxy):用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也成为外观代理(Facade Proxy)。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。
六、写入时复制代理(Copy-On-Write Proxy):用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止,这是虚拟代理的变体。
---------------------------------------------------------------


2、代理(Proxy)模式小结

*代理模式为另一个对象提供代表,以便控制客户对对象的访问,管理访问的方式有许多种。

*远程代理管理客户和远程对象之间的交互。

*虚拟代理控制访问实例化开销大的对象。

*保护模式基于调用者控制对对象方法的访问。

*代理模式有许多变体,例如:缓存代理、同步代理、防火墙代理与写入时复制代理。

*代理在结构上类似装饰者,但是目的不同。

*装饰者模式为对象加上行为,而代理控制访问。

*Java内置的代理支持,可以根据需要动态创建代理,并将所有调用分配到所选的处理器。

*和其它的包装者(wrapper)一样,代理会造成你的设计中类的数目的增加。

3、RMI(远程方法调用)实例
/**
 * 远程接口
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public interface HelloRemote extends Remote {
	String sayHello() throws RemoteException;
}

/**
 * 远程服务实现类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class HelloImpl extends UnicastRemoteObject implements HelloRemote {

	private static final long serialVersionUID = -5554845400316615009L;

	public static void main(String[] args) {
		try {
			HelloRemote helloRemote = new HelloImpl();
			Naming.rebind("HelloRemote", helloRemote);
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

	public HelloImpl() throws RemoteException {
	}

	@Override
	public String sayHello() throws RemoteException {
		return "Hello,world.I am zangweiren.";
	}
}

/**
 * 远程服务客户端
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class HelloClient {

	public static void main(String[] args) {
		try {
			HelloRemote helloRemote = (HelloRemote) Naming
					.lookup("rmi://127.0.0.1/HelloRemote");
			String words = helloRemote.sayHello();
			System.out.println(words);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		}
	}

}


4、远程代理(Remote Proxy)模式实例

/**
 * 服务器远程接口
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public interface ServerRemote extends Remote {
	void shutdown() throws RemoteException;

	void startup() throws RemoteException;
}

/**
 * 服务器实现类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class ServerImpl extends UnicastRemoteObject implements ServerRemote {

	private static final long serialVersionUID = -1466325816915299894L;

	public static void main(String[] args) {
		ServerRemote server;
		try {
			server = new ServerImpl();
			Naming.rebind("ServerRemote", server);
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

	public ServerImpl() throws RemoteException {
	}

	@Override
	public void shutdown() throws RemoteException {
		System.out.println("The server is shutdown.");
	}

	@Override
	public void startup() throws RemoteException {
		System.out.println("The server is running...");
	}
}

/**
 * 远程代理客户端测试程序
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class TestServer {
	public static void main(String[] args) {
		try {
			ServerRemote server = (ServerRemote) Naming.lookup("ServerRemote");
			server.startup();
			server.shutdown();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		}
	}
}


测试结果:

引用
The server is running...
The server is shutdown.


5、虚拟代理(Virtual Proxy)模式实例(结合了状态模式)

/**
 * 视频播放器
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public interface MediaPlayer {
	int getHeight();

	int getWidth();

	void play();
}

/**
 * 视频播放器实现类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class MediaPlayerImpl implements MediaPlayer {

	@Override
	public int getHeight() {
		return 1024;
	}

	@Override
	public int getWidth() {
		return 768;
	}

	@Override
	public void play() {
		System.out.println("The vedio is playing...");
	}

}

/**
 * 视频播放器状态
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public interface MediaPlayerState extends MediaPlayer {

}

/**
 * 未加载状态
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class NotLoadedState implements MediaPlayerState {
	private MediaPlayerProxy player;

	public NotLoadedState(MediaPlayerProxy player) {
		this.player = player;
	}

	@Override
	public int getHeight() {
		return 800;
	}

	@Override
	public int getWidth() {
		return 600;
	}

	@Override
	public void play() {
		player.setState(player.getLoadingState());
		player.play();
	}

}

/**
 * 加载中状态
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class LoadingState implements MediaPlayerState {

	private MediaPlayerProxy player;

	public LoadingState(MediaPlayerProxy player) {
		this.player = player;
	}

	@Override
	public int getHeight() {
		return 800;
	}

	@Override
	public int getWidth() {
		return 600;
	}

	@Override
	public void play() {
		for (int i = 0; i < 3; i++) {
			System.out.println("The video is loading,please wait...");
		}
		System.out.println("Video loaded.");
		player.setState(player.getLoadedState());
		player.play();
	}

}

/**
 * 已加载状态
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class LoadedState implements MediaPlayerState {
	private MediaPlayerProxy player;

	public LoadedState(MediaPlayerProxy player) {
		this.player = player;
	}

	@Override
	public int getHeight() {
		return 1024;
	}

	@Override
	public int getWidth() {
		return 768;
	}

	@Override
	public void play() {
		for (int i = 0; i < 5; i++) {
			System.out.println("The video is playing...Height:"
					+ player.getHeight() + ",Width:" + player.getWidth());
		}
		System.out.println("Finished.");
		player.setState(player.getNotLoadedState());
	}

}

/**
 * 视频播放器代理类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class MediaPlayerProxy implements MediaPlayer {
	private MediaPlayerState notLoaded;
	private MediaPlayerState loading;
	private MediaPlayerState loaded;
	private MediaPlayerState state;

	public MediaPlayerProxy() {
		notLoaded = new NotLoadedState(this);
		loading = new LoadingState(this);
		loaded = new LoadedState(this);

		state = notLoaded;
	}

	@Override
	public int getHeight() {
		return state.getHeight();
	}

	public MediaPlayerState getLoadedState() {
		return loaded;
	}

	public MediaPlayerState getLoadingState() {
		return loading;
	}

	public MediaPlayerState getNotLoadedState() {
		return notLoaded;
	}

	public MediaPlayerState getState() {
		return state;
	}

	@Override
	public int getWidth() {
		return state.getWidth();
	}

	@Override
	public void play() {
		state.play();
	}

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

}

测试程序:
/**
 * 视频播放器测试程序
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class TestMediaPlayer {

	public static void main(String[] args) {
		MediaPlayer player = new MediaPlayerProxy();
		System.out.println("Height:" + player.getHeight() + ",Width:"
				+ player.getWidth());
		player.play();
		System.out.println("Height:" + player.getHeight() + ",Width:"
				+ player.getWidth());
	}

}


测试结果:
引用
Height:800,Width:600
The video is loading,please wait...
The video is loading,please wait...
The video is loading,please wait...
Video loaded.
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
The video is playing...Height:1024,Width:768
Finished.
Height:800,Width:600



6、保护代理(Protect Proxy)模式实例

/**
 * 用户管理类接口
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public interface UserManager {

	public abstract void addUser(String name);

	public abstract void deleteUser(String name);

	public abstract void updateUser(String name,
			HashMap<String, String> properties);

}

/**
 * 用户管理类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class UserManagerImpl implements UserManager {
	@Override
	public void addUser(String name) {
		System.out.println("User:" + name + " has been added.");
	}

	@Override
	public void deleteUser(String name) {
		System.out.println("User:" + name + "has been deleted.");
	}

	@Override
	public void updateUser(String name, HashMap<String, String> properties) {
		System.out.println("User:" + name + "has been updated.");
		System.out.println("Properties:");
		Iterator<String> keys = properties.keySet().iterator();
		String key;
		while (keys.hasNext()) {
			key = keys.next();
			System.out.println(key + "=" + properties.get(key));
		}
		System.out.println("--------------");
	}
}

/**
 * 管理员处理类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class AdminInvocationHandler implements InvocationHandler {
	private UserManager manager;

	public AdminInvocationHandler(UserManager manager) {
		this.manager = manager;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws IllegalAccessException {
		try {
			if (method.getName().equals("addUser")) {
				return method.invoke(manager, args);
			} else if (method.getName().equals("updateUser")) {
				return method.invoke(manager, args);
			} else if (method.getName().equals("deleteUser")) {
				return method.invoke(manager, args);
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

}

/**
 * 普通用户处理类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class UserInvocationHandler implements InvocationHandler {
	private UserManager manager;

	public UserInvocationHandler(UserManager manager) {
		this.manager = manager;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws IllegalAccessException {
		try {
			if (method.getName().equals("addUser")) {
				throw new IllegalAccessException();
			} else if (method.getName().equals("updateUser")) {
				return method.invoke(manager, args);
			} else if (method.getName().equals("deleteUser")) {
				throw new IllegalAccessException();
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

}

/**
 * 工具类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class UserManagerUtils {
	public static UserManager getAdminProxy(UserManager manager) {
		return (UserManager) Proxy.newProxyInstance(manager.getClass()
				.getClassLoader(), manager.getClass().getInterfaces(),
				new AdminInvocationHandler(manager));
	}

	public static UserManager getUserProxy(UserManager manager) {
		return (UserManager) Proxy.newProxyInstance(manager.getClass()
				.getClassLoader(), manager.getClass().getInterfaces(),
				new UserInvocationHandler(manager));
	}
}

/**
 * 测试类
 * 
 * @author zangweiren 2010-4-8
 * 
 */
public class TestUserManager {

	public static void main(String[] args) {
		UserManager manager = new UserManagerImpl();
		UserManager admin = UserManagerUtils.getAdminProxy(manager);
		admin.addUser("Jim");
		HashMap<String, String> properties = new HashMap<String, String>();
		properties.put("Gender", "male");
		properties.put("Age", "28");
		admin.updateUser("Jim", properties);
		admin.deleteUser("Jim");
		System.out.println();

		UserManager user = UserManagerUtils.getUserProxy(manager);
		try {
			user.addUser("Lily");
		} catch (Exception e) {
			System.out.println("Can't add User!");
		}
		properties = new HashMap<String, String>();
		properties.put("Gender", "female");
		properties.put("Age", "26");
		user.updateUser("Lily", properties);
		try {
			user.deleteUser("Lily");
		} catch (Exception e) {
			System.out.println("Can't delete User!");
		}
	}

}


测试结果:
引用
User:Jim has been added.
User:Jimhas been updated.
Properties:
Age=28
Gender=male
--------------
User:Jimhas been deleted.

Can't add User!
User:Lilyhas been updated.
Properties:
Age=26
Gender=female
--------------
Can't delete User!

你可能感兴趣的:(设计模式,jvm,多线程,防火墙)