代理模式是通过创建一个代理对象,使用这个代理对象代替实际对象。对于客户端而言,得到代理对象于操作而言没有任何影响。
当客户端操作代理对象时,实际上操作会由实际对象完成。即客户端操作代理对象,代理对象操作实际对象,而代理对象在操作实际对象时,可以添加额外的操作实现懒加载,权限限定等一系列额外操作。
代理分类:
1、 虚代理:根据需要创建开销很大的对象,而该对象只有在真正需要的时候才会被真正创建。实际应用------懒加载。
2、 远程代理:用来在不同的地址空间表示同一个对象。实际应用------RMI技术
3、 Copy-on-wirte:只有当对象确实改变了,才会拷贝一个目标对象。
4、 保护代理:控制对原始对象的访问。
下文则从最简单的静态代理开始讲解java中的代理模式:
以生活中销售手机为例,厂家生产手机,经销商从厂家拿货销售给客户。而在这个过程中,经销商就是厂家的代理。可以在厂家销售过程中增加一系列加价,满减等活动。而针对客户,买手机这一操作并没有因为是从经销商处购买收到影响。而经销商也是在厂家销售的基础上增加其他活动,完成整个代理。
1、公用接口
public interface SellProduct {
public int SellPhone(String phoneName);
}
2、实际对象厂家():
public class Producer implements SellProduct{
/**
* 模拟厂家定价
*/
@Override
public int SellPhone(String phoneName) {
// TODO Auto-generated method stub
int price = 0;
switch (phoneName) {
case "iphone":
price = 6000;
break;
case "mi":
price = 2499;
default:
break;
}
System.out.println("销售手机:"+phoneName+",价格:"+price);
return price;
}
}
3、代理对象(经销商):
public class Dealer implements SellProduct{
private Producer producer;
public Dealer(Producer producer) {
this.producer = producer;
}
/**
* 经销商不需要知道厂家如何定价,只要在出厂价基础上加价即可
*/
@Override
public int SellPhone(String phoneName) {
int price = producer.SellPhone(phoneName)+200;
System.out.println("销售手机:"+phoneName+",价格:"+price);
return price;
}
}
4、客户:
public class Client {
public static void main(String []args){
SellProduct sell = new Dealer(new Producer());
sell.SellPhone("iphone");
}
}
运行结果:
销售手机:iphone,价格:6200
以下介绍两种其他常用的代理模式:
一:虚代理(实际运用与懒加载):
在数据库中,往往需要一个对象有很多个属性,而一次性加载所有属性是对内存的极大浪费。如果我们第一次只查询必要的数据,而其他数据等到需要时再查询,无疑会大大减小内存的消耗。
1、接口:
public interface UserModel {
public int getId();
public void setId(int id);
public String getName();
public void setName(String name);
}
2、实际对象:
public class UserModelImpl implements UserModel {
private int id;
private String name;
@Override
public int getId() {
// TODO Auto-generated method stub
return id;
}
@Override
public void setId(int id) {
// TODO Auto-generated method stub
this.id = id;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}
public class ProxyModel implements UserModel{
private UserModelImpl userModel;
private boolean isLoad = false;
public ProxyModel(UserModelImpl userModel){
this.userModel = userModel;
}
@Override
public int getId() {
// TODO Auto-generated method stub
return userModel.getId();
}
@Override
public void setId(int id) {
// TODO Auto-generated method stub
userModel.setId(id);
}
@Override
public String getName() {
// TODO Auto-generated method stub
if(!this.isLoad){
reload();
this.isLoad = true;
}
return userModel.getName();
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
userModel.setName(name);
}
/**
* 重新从数据库中获取name注入实际对象
*/
private void reload(){
String name = getNameFromSQL();
System.out.println("重新从数据库加载数据");
userModel.setName(name);
}
/**
* 模拟从数据库获取name操作
* @return
*/
private String getNameFromSQL(){
return "simulation";
}
}
4、客户使用:
public class Client {
/**
* 模拟从数据库中查询,因为不需要知道其他属性,只注入id即可
* @param usermodel
*/
private static void SQLQuery(UserModel usermodel){
usermodel.setId(1);
}
public static void main(String []args){
ProxyModel proxy = new ProxyModel(new UserModelImpl());
SQLQuery(proxy);
System.out.println("id:"+proxy.getId());
System.out.println("name:"+proxy.getName());
}
}
运行结果:
id:1
重新从数据库加载数据
simulation
二 保护代理:
控制原始对象访问的代理。
1、接口:
public interface OAOperate {
public void add();
public void select();
public void delete();
}
2、原始对象:
public class OAOperater implements OAOperate{
private String name;
private int flag;
public OAOperater(String name,int flag) {
this.name = name;
this.flag = flag;
}
public int getFlag(){
return this.flag;
}
@Override
public void add() {
//省略相应操作
}
@Override
public void select() {
//省略相应操作
}
/**
* delete需要权限设置
*/
@Override
public void delete() {
//省略相应操作
System.out.println("删除操作");
}
}
3、代理对象:
public class OAProxy implements OAOperate {
private OAOperater operate;
public OAProxy(OAOperater operate) {
this.operate = operate;
}
@Override
public void add() {
// TODO Auto-generated method stub
}
@Override
public void select() {
// TODO Auto-generated method stub
}
@Override
public void delete() {
// TODO Auto-generated method stub
if (operate.getFlag() != 4) {
System.out.println("权限不足,不能修改");
} else {
operate.delete();
}
}
}
4、客户:
public class Client {
public static void main(String []args){
OAOperate operate = new OAProxy(new OAOperater("xiaoming", 3));
operate.delete();
OAOperate operater = new OAProxy(new OAOperater("paditang", 4));
operater.delete();
}
}
运行结果:
权限不足,不能修改
删除操作