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

1、代理(Proxy)模式部分

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

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

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

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

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

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

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

*远程代理(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);
}
}
---------------------------------------------------------------


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

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

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();
}
}
}


测试结果:

[quote]The server is running...
The server is shutdown.[/quote]

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());
}

}


测试结果:
[quote]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[/quote]


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!");
}
}

}


测试结果:
[quote]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![/quote]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值