以下笔记经阅读孙卫琴《java面向对象编程》而整理!
代理设计模式—房屋出租人
一、代理设计的概念
在日常生活中,会遇到各种各样的中介结构,比如猎头公司,律师事务所,房产公司等等,在这些单位中工作的人员,我们可以称为代理人。代理人的一个共同特点就是可以代替委托人和第三方通信。代理人可以在委托人和第三方之间转发消息和过滤消息,但是不能取代委托人的任务。比如,房屋租赁人交纳租金,房产代理人不会将佣金私吞,而是由出租人领取租金。
代理设计模式也可以运用到面向对象的软件开发领域中,它的特征是:代理类和委托类有同样的接口。代理类主要负责委托类预处理消息,过滤消息以及把消息转发给委托类,代理类和委托类之间为组合关系。如下图所示,代理人与委托人的关系。
二、代理设计的程序实现
2.1 定义接口
定义一个接口RenterIFC,该接口定义了出租人的两个行为:
-| 决定是否同意按租赁人提出的价格出租房屋
-| 收房租
程序:
package com.wisdragon.oo1.proxydesignpattern2;
/**
* 描述: 定义出租人的两个行为:决定是否同意出租按租赁人提出的价格出租房屋以及收房租
*/
public interface RenterIFC {
//是否同意按租赁人提出的价格出租房屋
public boolean isAgree(double expectedRent);
//收房租
public void fetchRent(double rent);
}
为了程序的简单易实现,假设一个代理人只对应一个出租人,租赁人租房屋rentHouse()的大致过程如下:
- 从房产市场找一个房产代理人,即调用HouseMarket对象的findRenter()方法。
- 报出期望的租金价格,征求代理人的意见,即调用Deputy对象的isAgree()方法。
- 代理人处理的方式为: 如果租赁人的报价低于出租人的租金价格底线,就立即做出拒绝答复;否则征求出租人的意见,即调用Renter对象的isAgree()方法。
- 出租人的处理方式为: 如果租赁人的报价比租金价格底线多100元,就同意出租。
- 如果租赁人得到代理人同意租房的答复,就从存款中取出现金,通知代理人领取租金,即调用Deputy对象的fetchRent()方法。
上面的流程可以使用以下的时序图表示。
2.2 程序实现
程序:出租人
package com.wisdragon.oo1.proxydesignpattern2;
/**
* 描述: 出租人信息
*/
public class Rent implements RenterIFC {
private double rentDeadLine; //房屋出租最低价格
private double money; //存款
public Rent(double rentDeadLine, double money) {
super();
this.rentDeadLine = rentDeadLine;
this.money = money;
}
public double getRentDeadLine() {
return rentDeadLine;
}
public void setRentDeadLine(double rentDeadLine) {
this.rentDeadLine = rentDeadLine;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public void fetchRent(double rent) {
this.money += rent;
}
@Override
public boolean isAgree(double expectedRent) {
//如果租赁人的期望价格比租金的最低价格多100元,则同意出租
return (expectedRent - this.rentDeadLine) > 100;
}
}
程序:代理人
package com.wisdragon.oo1.proxydesignpattern2;
/**
* 描述: 代理人信息
* 更新记录:
*/
public class Deupty implements RenterIFC {
private Rent rent;
public void registerRenter(Rent rent){
this.rent = rent;
}
@Override
public void fetchRent(double rent) {
//收租金
this.rent.fetchRent(rent);
}
@Override
public boolean isAgree(double expectedRent) {
//如果租赁人的期望价格低于租金的最低价格,则拒绝并答复
if(expectedRent < this.rent.getRentDeadLine()){
return false;
}
//否则请示出租人的意见,租赁人的价格还可以考虑
return this.rent.isAgree(expectedRent);
}
}
程序:房产市场
package com.wisdragon.oo1.proxydesignpattern2;
import java.util.HashSet;
import java.util.Set;
/**
* 描述: 房产市场
* 更新记录:
*/
public class HourseMarket {
private static Set<RenterIFC> renters = new HashSet<RenterIFC>();
public static void registerRenter(RenterIFC renterifc){
renters.add(renterifc);
}
public static RenterIFC findRenter(){
return (RenterIFC)renters.iterator().next();
}
}
程序:租赁人
package com.wisdragon.oo1.proxydesignpattern2;
/**
* 描述: 租赁人
* 更新记录:
*/
public class Tenant {
private double money;
public Tenant(double money) {
super();
this.money = money;
}
public boolean rentHourse(double expectRent){
//从房产市场找一个代理人
RenterIFC renter = HourseMarket.findRenter();
//如果代理人不同意预期租金价格就拉倒,否则继续执行
if(!renter.isAgree(expectRent)){
return false;
}
//从存款中取出预付租金
this.money -= expectRent;
//将租金交给代理人
renter.fetchRent(expectRent);
return true;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
程序:主程序
package com.wisdragon.oo1.proxydesignpattern2;
public class AppMain {
/**
* 作者: 黄玉泽
* 创建日期: Nov 7, 2014 9:51:49 PM
* 参数信息: @param args
* 返回值: void
* 描述: 测试代理类
*/
public static void main(String[] args) {
//创建一个房屋出租人,租金最低价格为2000,存款一万元
Rent rent = new Rent(2000, 10000);
//创建一个房产代理人
Deupty deupty = new Deupty();
//建立房屋出租人与代理人的委托关系
deupty.registerRenter(rent);
//将此代理人注册到房产市场中
HourseMarket.registerRenter(deupty);
//创建一个房屋租赁人,存款为20000元
Tenant tenant = new Tenant(20000);
//房屋租赁人试图找一个1800元的房屋,遭房产代理人拒绝
boolean flag = tenant.rentHourse(1800);
if(flag){
System.out.println("租房成功,租房者存款: " + tenant.getMoney());
System.out.println("出租成功,出租者存款: " + rent.getMoney());
}else{
System.out.println("出租失败,出租者存款: " + rent.getMoney());
System.out.println("租房失败,租房者存款: " + tenant.getMoney());
}
System.out.println("*************************************************");
//房屋租赁人试图找一个2200元的房屋,租房成功
flag = tenant.rentHourse(2200);
if(flag){
System.out.println("租房成功,租房者存款: " + tenant.getMoney());
System.out.println("出租成功,出租者存款: " + rent.getMoney());
}else{
System.out.println("出租失败,出租者存款: " + rent.getMoney());
System.out.println("租房失败,租房者存款: " + tenant.getMoney());
}
}
}
以上 租赁人、出租人、代理类 类框图如下:
三、总结
事实上,如果没有代理人,让租赁人直接和出租人直接沟通,也能进行房屋交易。如果出租人能够方便地与租赁人沟通联系,并且出租人有足够的时间去接待多有潜在的客户,那么不经过代理反而会提高办事效率。假如出租人与租赁人联系很不方便,假设出租人在北京,但有一套房子在上海要出租,出租人工作繁忙,没有足够的时间和所有潜在的客户谈判租金,那么房产代理人会很方便地为出租人和租赁人建立沟通桥梁。
在软件系统中,假如Tenant对象和Rent对象分部子在不同的机器上,即运行在不同的java虚拟机上,那么,Tenant对象和Rent对象进行频繁地远程通信的效率会比较低。在这种情况下,可以在Tenant对象所在的机器上安置Rent对象的代理Deupty对象,Tenat对象之和Deupty对象通信,当Tenat的报价太低时,Dupty对象就能立即回绝Tenat对象,无需把消息发送给Rent对象,这样可以减少远程通信的次数。提高效率。见下图: