软件构造习题课重点总结(停车场)

1 给出一个 Java ADT 题目
某公司拟设计和开发一个停车场管理系统,其基本需求陈述如下:
(1) 一个停车场有 n 个车位(n>=5),不同停车场包含的车位数目不同。
(2) 一辆车进入停车场,如果该停车场有空车位且其宽度足以容纳车的宽度,则可以
在此停车。
(3) 停在停车场里的车,随时可以驶离停车场,根据时间自动计费(每半小时 10
元,不足半小时按半小时计算)。
(4) 停车场管理员可以随时查看停车场的当前占用情况。

分析客户端的需求:

采用名词分析法和动词分析法,即提炼出名词和动词来识别自己需要构造的ADT。

名词:停车场、车、车位、车位的宽度、车的宽度、入场时间、出场时间、一次停车得全过程

动词:停车、 驶离、计费、查看状态。

简要列出名词和动词之后可以初步列出想要构造得adt

停车场包含车位数

车包含车牌号、车的宽度

车位包含编号、车位宽度

设计原则:尽可能缩小mutable的范围

一次停车的全过程这个名词有些复杂,涉及到车、入场时间、出场时间、所在车位、费用,不同策略如下:

本次采用第四种方法,即停车场类中管理一次停车的全过程。

编程方法:考虑到将来变化与不同的实现方式,采用接口设计停车场ADT

设计接口的过程:

1.写spec

2.识别ADT的四种操作类型

Parking(Car c,Lot lot)中自己构造的具体对象建议隐藏,传入所需的基本信息在函数中构造,如果不希望把 Car 暴露出去,可改成 parking(String plate, int width, int num), parking(String plate, int width)

 

需求中的特殊情况怎么处理?
 停车进场的时候(两种情况):该车辆已经在停车场里面了
 停车进场的时候(不指定车位):停车场已没有可供该车停车的位置
 停车进场的时候(指定车位):该车位已被占用、该车位过窄、没有该车位
 驶离停车场的时候:该车并没有停在这里
建议的处理方式:
 更强的规约:更弱的前置前置、更强的后置条件,让 client 使用更容易,把责任
放在实现者身上。
 太弱的 spec,client 不放心、不敢用 (因为没有给出足够的承诺)。开发者应尽
可能考虑各种特殊情况,在 post-condition 给出处理措施。
 惯用做法是:不限定太强的 precondition,而是在 postcondition 中抛出异常:
输入不合法。
 例如:针对“停车进场的时候(不指定车位),停车场已没有可供该车停车的位置“这
种情况,无法限定 client 已知停车场是否已满,所以不能在 pre 里写,而是交给
post 来处理。
 所以,可以针对上述特殊情况,在 post 里使用异常,告知 client。
 考虑到目前尚未学习如何定义异常,这里先采用通用的异常类 Exception。
静态工厂方法和实例方法的测试,分开。让测试类的职责更清晰。
使用 Factory Method 设计模式:可维护性

 

        建立一个用于装饰的基础类ComplexParkingField ,实现ParkingField接口,其中的所
有方法都delegate到未装饰之前的对象。
        然后,建立一个具体装饰类ParkingFieldWithCompany,也实现ParkingField接口,继
承自ComplexParkingField类,增加了rep(公司信息),对需要变化的方法进行扩展 (使用super.xxx()调用基础功能)。修改构造函数,增加company参数。例如:
 
@Override
public double depart(String plate) throws Exception {

double price = super.depart(plate);
println(plate + ", " + company + " wish you a good drive");

return price;
}

 使用 Visitor 设计模式:可扩展性

        建立 visitor 接口 ParkingVisitor,只有一个方法 double visit(parkingField
pf)。
         建立其子类 PercentageVisitor,实现该 visit 方法,调用 pf 的方法获得 pf 的内
部表示,进行计算。
         在 ParkingField 接口中增加 accept(ParkingVisitor pv)方法,其实现很简单:
pv.visit(this)。
        客户端只需要使用 double ratio = pf.accept(new PercentageVisitor())即可。 如果要为 ParkingField 扩展另一个操作呢?只需要构造 ParkingVisitor 的另一个子类 型,在其 visit()中实现新功能,客户端调用 pf.accept()的时候传入新子类的对象即可。

使用 Strategy 设计模式:可扩展性、可维护性
        ParkingField 接口中定义了一个方法 void parking(String type, String plate, int width),与另一个带有 num 车位号的 parking 方法相比,使用该方法的 client 端无 需提供“停车位号码”信息,而是在方法内部自动进行空闲停车位的选择。现实中有不同的停 车位选择方法,例如:
(1) 随机选择一个空闲的、宽度大于车辆宽度的停车位;
(2) 根据停车位编号,优先选择编号最小的空闲停车位,且其宽度大于车辆宽度。
        使用 Strategy 设计模式改造现有设计:在客户端代码调用 void parking(String type, String plate, int width)的时候,
        如何动态传入某个特定的停车位选择方法?
本质上,相当于写两个停车位选择算法,但不直接在 ConcreteParkingField 里写,而是
delegate 出去到外部的 Strategy 具体实现类,跟上面的几个设计模式非常像。
最终停车场整体类图

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值