从制造到创造
软件工程师成长之路
posts - 292,  comments - 96,  trackbacks - 0

8.1 接口的概念和基本特征

(1)、接口中的成员变量默认都是public、static、final类型的,必须被显式初始化;
(2)、接口中的方法默认都是public、abstract类型的;
(3)、接口中只能包含public、static、final类型的成员变量和public、abstract类型的成员方法;
(4)、接口没有构造方法,不能被实例化;
(5)、一个接口不能实现另一个接口,但可以继承多个其他接口;
(6)、接口必须通过类来实现它的抽象方法。类实现接口的关键字是implements;
(7)、与子类继承抽象父类相似,当类实现了某个接口时,它必须实现接口中所有的抽象方法,否则这个类必须被定义为抽象类;
(8)、不允许创建接口类型的实例,但允许定义接口类型的引用变量,该变量引用实现了这个接口的类的实例;
(9)、一个类只能继承一个直接的父类,但能实现多个接口。

8.2 比较抽象类与接口

相同点:
  • 代表系统的抽象层
  • 都不能被实例化
  • 都能包含抽象方法
两大区别:
  • 在抽象类中可以为部分方法提供默认的实现,从而避免在子类中重复实现它们,提高代码的可重用性,这是抽象类的优势所在;而接口中只能包含抽象方法;
  • 一个类只能继承一个直接的父类,这个父类有可能是抽象类;但一个类可以实现多个接口,这是接口的优势所在。 
使用接口和抽象类的原则:
  1. 用接口作为系统与外界交互的窗口;
  2. 由于外界使用者依赖系统的接口,并且系统内部会实现接口,因此接口本身必须十分稳定,接口一旦制订,就不允许随意修改,否则会对外界使用者及系统内部都造成影响。
  3. 用抽象类来定制系统中的扩展点。 

8.3 与接口相关的设计模式

8.3.1 定制服务模式
如何设计接口?定制服务模式提出了设计精粒度的接口的原则。
8.3.2 适配器模式

当两个系统之间接口不匹配时,如果处理?适配器模式提供了接口转换方案。

包括继承实现方式和组合实现方式。优先考虑用组合关系来实现适配器。

8.3.3 默认适配器模式
为了简化编程,JDK为MouseListener提供了一个默认适配器MouseAdapter,它实现了MouseListener接口,为所有的方法提供了空的方法体。用户自定义的MyMouseLIstener监听器可以继承MouseAdapter类,在MyMouseListener类中,只需要覆盖特定的方法,而不必实现所有的方法。使用默认适配器可以简化编程,但缺点是该类不能在继承其他的类。
8.3.4 代理模式

下面以房屋出租人的代理为例,介绍代理模式的运用。在下图中,出租人Renter和代理Deputy都具有RenterIFC接口。Tenant类代表租赁人,HouseMarket类代表整个房产市场,它记录了所有房产代理人的信息,出租人从房产市场找到房产代理人。



为了简化起见,假定一个代理人只会为一个出租人做代理,租赁人租房屋rentHouse()的大致过程如下:

  1. 从房产市场上找到一个房产代理人,即调用HouseMarket对象的findRenter()方法;
  2. 报出期望的租金价格,征求代理人的意见,即调用Deputy对象的isAgree()方法;
  3. 代理人的处理方式为:如果租赁人的报价低于出租人的租金价格底线,就立即做出拒绝答复;否则征求出租人的意见,即调用Renter对象的isAgree()方法。
  4. 出租人的处理方式为:如果租赁人的报价比租金价格底线多100元,就同意出租
  5. 如果租赁人得到代理人同意的答复,就从存款中取出租金,通知代理人领取租金,即调用Deputy对象的fetchRent()方法
  6. 代理人通知出租人领取租金,即调用Renter对象的fecthRent()方法。 


 房屋租赁交易顺利执行的时序图

源代码:

/**
 * RetnerIFC 接口,它定义了出租人的两个行为,即决定是否同意按租赁人提出的价格出租房屋,以及收房租
 * 
 * 
@author XL
 * 
 
*/
public interface RenterIFC {
    
/**
     * 是否同意按租赁人提出的价格出租房屋
     * 
     * 
@param expectedRent
     * 
@return
     
*/
    
public boolean isAgree(double expectedRent);

    
/**
     * 收房租
     * 
     * 
@param rent
     
*/
    
public void fetchRent(double rent);
}


/**
 * 房屋出租人
 * 
 * 
@author XL
 * 
 
*/
public class Renter implements RenterIFC {

    
/**
     * 房屋租金最低价格
     
*/
    
private double rentDeadLine;

    
/**
     * 存款
     
*/
    
private double money;

    
/**
     * 
@param rentDeadLine
     * 
@param money
     
*/
    
public Renter(double rentDeadLine, double money) {
        
super();
        System.out.println(
"New Renter, rentDeadLine: " + rentDeadLine
                
+ ", saveMoney: " + money);
        
this.rentDeadLine = rentDeadLine;
        
this.money = money;
    }

    
/*
     * (non-Javadoc)
     * 
     * @see chapter08.d0800.RenterIFC#fetchRent(double)
     
*/
    
public void fetchRent(double rent) {
        System.out.println(
"OK, you can use the house.");
        money 
+= rent;
    }

    
/*
     * (non-Javadoc) 如果租赁人的期望价格比房屋租金最低价格多100元,则同意出租
     * 
     * @see chapter08.d0800.RenterIFC#isAgree(double)
     
*/
    
public boolean isAgree(double expectedRent) {
        System.out.println(
"If the money less 100 than the rentDeadLine.");
        
return expectedRent - this.rentDeadLine > 100;
    }

    
/**
     * 
@return
     
*/
    
public double getRentDeadLine() {
        
return rentDeadLine;
    }
}


/**
 * 房产代理人
 * 
 * 
@author XL
 * 
 
*/
public class Deputy implements RenterIFC {

    
private Renter renter;

    
/**
     * 接受代理
     * 
     * 
@param renter
     
*/
    
public void registerRenter(Renter renter) {
        System.out.println(
"OK, I have some business.");
        
this.renter = renter;
    }

    
public void fetchRent(double rent) {
        System.out.println(
"Get the monty: " + rent);
        renter.fetchRent(rent);
    }

    
/*
     * (non-Javadoc) 如果租赁人的期望价格低于房屋租金最低价格,则不同意出租 否则请示出租人的意见
     * 
     * @see chapter08.d0800.RenterIFC#isAgree(double)
     
*/
    
public boolean isAgree(double expectedRent) {
        
//
        if (expectedRent < renter.getRentDeadLine()) {
            System.out.println(
"Sorry, you can't rent the house.");
            
return false;
        } 
else {
            System.out.println(
"Let me ask the renter.");
            
return renter.isAgree(expectedRent);
        }
    }

}

 

import java.util.HashSet;
import java.util.Set;

/**
 * 
@author XL
 * 
 
*/
public class HouseMarket {
    
private static Set<RenterIFC> renters = new HashSet<RenterIFC>();

    
public static void registerRenter(RenterIFC deputy) {
        System.out.println(
"A new man has registered!");
        renters.add(deputy);
    }

    
public static RenterIFC findRenter() {
        System.out.println(
"Let's find something!");
        
return (RenterIFC) renters.iterator().next();
    }
}

 

/**
 * 房屋租赁人
 * 
 * 
@author XL
 * 
 
*/
public class Tenant {
    
private double money;

    
public Tenant(double money) {
        
// 
        System.out.println("New Tenant!");
        System.out.println(
"I have " + money);
        
this.money = money;
    }

    
public boolean rentHouse(double expectedRent) {
        
// 从房地产市场找到一个房产代理人
        RenterIFC renter = HouseMarket.findRenter();
        
        System.out.println(
"I can offer " + expectedRent);
        
        
// 如果代理人不同意预期的租金价格,就拉倒,否则继续执行
        if (!renter.isAgree(expectedRent)) {
            System.out.println(
"I can't offer any more!");
            
return false;
        }

        
// 从存款中取出预付租金
        money -= expectedRent;
        System.out.println(
"OK, get the money, " + expectedRent);

        
// 把租金交给房产代理人
        renter.fetchRent(expectedRent);

        
return true;
    }
}

 

/**
 * 
@author XL
 *
 
*/
public class AppMain {

    
/**
     * 
@param args
     
*/
    
public static void main(String[] args) {
        
// 创建一个房屋出租人,房屋租金最低价格为2000元,存款1万元
        Renter renter = new Renter(200010000);
        
        
// 创建一个房产代理人
        Deputy deputy = new Deputy();
        
        
// 房产代理人到房产市场登记
        HouseMarket.registerRenter(deputy);
        
        
// 建立房屋出租人和房产代理人的委托关系
        deputy.registerRenter(renter);
        
        
        
// 创建一个房屋租赁人,存款为2万元
        Tenant tenant = new Tenant(20000);
        
        
// 房屋租赁人试图租赁期望租金为1800元的房屋,遭到房产代理人拒绝
        tenant.rentHouse(1800);
        
        
// 房屋租赁人试图租赁期望租金为2300元的房屋,租房成功
        tenant.rentHouse(2300);
    }

}

输出结果:

New Renter, rentDeadLine: 2000.0, saveMoney: 10000.0
A new man has registered!
OK, I have some business.
New Tenant!
I have 20000.0
Let's find something!
I can offer 1800.0
Sorry, you can't rent the house.
I can't offer any more!
Let's find something!
I can offer 2300.0
Let me ask the renter.
If the money less 100 than the rentDeadLine.
OK, get the money, 2300.0
Get the monty: 2300.0
OK, you can use the house.


8.3.5 标识类型模式

标识类型接口没有任何方法,仅代表一种抽象类型。
在JDK中,有如下两个典型的标识类型接口:

  • java.io.Serializable接口:实现该接口的类可以被序列化。
  • java.io.Remote接口:实现该接口的类的实例可以作为远程对象。
8.3.6 常量接口模式
posted on 2008-02-19 18:03 CoderDream 阅读(395) 评论(0)  编辑  收藏 所属分类: 经验点滴

只有注册用户登录后才能发表评论。


网站导航:
 

<2008年2月>
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678

常用链接

留言簿(9)

我参与的团队

随笔分类(245)

随笔档案(239)

文章分类(3)

文章档案(3)

收藏夹(576)

友情链接

搜索

  •  

积分与排名

  • 积分 - 456206
  • 排名 - 114

最新评论

阅读排行榜

评论排行榜