目录
1. 策略模式类图与代码
某大型购物中心欲开发一套收银软件,要求其能够支持购物中心在不同时期推出的各种促销活动,如打折、返利(例如,满300返100),等等。现采用策略(Strategy)模式实现该要求,得到如图7.13 所示的类图。
【Java 代码】
import java.util.*;
enum TYPE { NORMAL,CASH_DISCOUNT,CASH_RETURN};
interface Cashsuper {
public double acceptCash(double money);
}
class CashNormal implements CashSuper{// 正常收费子类
public double accptCash(double money){
return money;
}
}
class CashDiscount implements Cashsuper {
private double moneyDiscount; //折扣率
public CashDiscount(double moneyDiscount){
this moneyDiscount = moneyDiscount;
}
public double acceptCash(double money){
return money* moneyDiscount;
}
}
class CashReturn implements Cashsuper { //满额返利
private double moneyCondition;
private double moneyReturn;
public CashReturn(double moneyCondition, double moneyReturn){
this.moneycondition =moneyCondition;//满额数额
this.moneyReturn =moneyReturn;//返利数额
}
public double acceptCash(double money){
double result = money;
if (money >= moneyCondition )
result=money-Math.floor(money/moneyCondition )* moneyReturn;
return result;
}
}
class CashContext{
private Cashsuper cs;
private TYPE t;
public CashContext(TYPE t){
switch(t){
case NORMAL;// 正常收费
cs= new CashNormal();
break;
case CASH_RETURN;//满300返100
cs = new CashReturn(300,100);
break;
case CASH_DISCOUNT;//打8折
cs =new CashDiscount(0.8);
break;
}
}
public double GetResult(double money){
return cs.acceptCash(money);
}
//此处略去main()函数:选择哪一种策略,输入金额
}
2. 适配器模式类图与代码
某软件系统中,已设计并实现了用于显示地址信息的类Address,现要求提供基于Dutch语言的地址信息显示接口。为了实现该要求并考虑到以后可能还会出现新的语言的接口,决定采用适配器(Adapter)模式实现该要求,得到如图7.9所示的类图。
【Java代码】
import java.util.*;
Class Address{ // 现有接口
public void street(){
//实现代码省略
}
public void zip(){
//实现代码省略
}
public void city(){
//实现代码省略
}
//其他成员省略
}
class DutchAddress { // 目标接口
public void straat() {
//实现代码省略
}
public void postcode() {
//实现代码省略
}
public void plaats() {
//实现代码省略
}
//其他成员省略
}
class DutchAddressAdapter extends DutchAddress { // 为目标对象创建适配器
private Address address;
public DutchAddressAdapter(Address addr) {
address = addr;
}
public void straat() {
address.street();
}
public void postcode() {
address.zip();
}
public void plaats() {
address.city();
}
//其他成员省略
}
class Test {
public static void main(String[] args) {
// 利用适配器传入一个现有的接口对象,创建一个目标接口对象,再调用目标对象的方法
Address addr = new Address();
DutchAddress addrAdapter=new DutchAddressAdaptor(addr);
System.out.println("\n The DutchAddress\n");
testDutch(addrAdapter);
}
static void testDutch(DutchAddress addr) {
addr.straat();
addr.postcode();
addr.plaats();
}
}
3. 访问者模式类图与代码
某图书管理系统中管理着两种类型的文献:图书和论文。现在要求统计所有馆藏文献的总页码(假设图书馆中有一本540页的图书和两篇各25页的论文,那么馆藏文献的总页码就是590页)。采用Visitor(访问者)模式实现该要求,得到如图7.16所示的类图。
访问者模式让增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
【Java 代码】
import java.util.*;
interface Libraryvisitor { // 抽象访问者
void visit(Book p_book); //访问Book
void visit(Article p_article);//访问 Article
void printSum();
}
class LibrarysumPrintvisitor implements Libraryvisitor {// 访问者
private int sum = 0;
public void visit(Book p_book) {
sum = sum + p_book.getNumberOfPages();
}
public void visit (Article p_article){
sum = sum + p_article.getNumberOfPages;
}
public void printsum () {
System.out.println("SUM=" + sum);
}
}
interface libraryItemInterface {
void accept(LibraryVisitor visitor); // 声明了一个接受操作,接受一个访问者对象
}
class Article implements libraryItemInterface {
private String m_title; //论文名
private String m_author; //论文作者
private int m_start_page;
private int m_end_page;
public Article(String p_author, String p_title, int p_start_page, int
p_end_page) {
m_title = p_title;
m_author = p_author;
m_start_page = p_start_page;
m_end_page = p_end_page;
}
public int getNumberOfPages() {
rctum m_end_page - m_start_page;
}
public void accept(Libraryvisitor visitor) { // 接收一个访问者,统计Book的页数
visitor.visit(this);
}
}
class Book implements LibraryItemInterface {
private String m_title; //书名
private String m_author;//书作者
private int m_pages;//页数
public Book(String p_author, String p_title, int p_ pages) {
m_title = p_title;
m_author = p_author;
m_pages = p_pages;
}
public int getNumberOfPages() {
return m_pages;
}
public void accept(Libraryvisitor visitor) { // 接收一个访问者,统计Article的页数
visitor.visit(this);
}
}
4. 原型模式类图与代码
现要求实现一个能够自动生成求职简历的程序,简历的基本内容包括求职者的姓名、性别、年龄及工作经历。希望每份简历中的工作经历有所不同,并尽量减少程序中的重复代码。
采用原型模式(Prototype)来实现上述要求,得到如图 7.25 所示的类图。
原型模型是一种对象创建模型,用原型实体指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模型允许一个对象再创建另一个可定制的对象,无须知道任何创建的细节。
【Java代码】
public class WorkExperience implements Cloneable{//工作经历
private String workDate;
private String company;
public Object clone {
WorkExperience Obj = new WorkExperience();
Obj.workDate = this.workDate;
Obj.company = this.company;
return Obj;
}
//其余代码省略
}
public class Resume implements Cloneable{//简历
private String name;
private String sex;
private String age;
private WorkExperience work;
public Resume(String name){
this.name = name;
work = new WorkExperience();
}
private Resume(WorkExperience work){
this.work = (WorkExperience)work.clone();
}
public void SetPersonInfo(String sex,String age){/*实现省略*/}
public void SetWorkExperience(String workDate,String company){/*实现省略*/}
public Object clone(){
Resume Obj = new Resume(this.work);
return Obj;
}
}
Class WorkResume{
public static void main(){
Resume a = new Resume("张三");
a.SetPersonInfo("男","29");
a.SetWorkExperience("1998-2000","XXX公司");
Resume b = (Resume)a.clone();
b.SetWorkExperience("2001-2006","YYY公司");
}
}
5. 桥接模式类图与代码
欲开发一个绘图软件,要求使用不同的绘图程序绘制不同的图形。以绘制直线和圆形为例,对应的绘图程序如表 7.7 所示。
根据绘图软件的扩展性要求,该绘图软件将不断扩充新的图形和新的绘图程序。为了避免出现类爆炸的情况,现采用桥接(Bridge)模式来实现上述要求,得到如图 7.21 所示的类图。
桥接模式将抽象与其实现解耦,使它们都可以独立地变化。也就是说:将一组实现与另一组使用它们的对象分离。这里的实现指的是抽象类及其派生类用来实现自己的对象(而不是抽象类的派生类,这些派生类被称为具体类)。
【Java代码】
public abstract class Drawing {
public abstract void drawLine(double xl,double yl,double x2,double y2);
public abstract void drawCircle(double x,double y,double r);
}
public class DP1 {
public static void draw_a_line(double xl,double yl,double x2,double y2){
/*代码省略 */
}
public static void draw_a_circle(double x,double y,double r){
/*代码省略 */
}
}
public class DP2 {
public static void drawLine(double xl,double x2,double yl,double y2) {
/*代码省略 */
}
public static void drawCircle(double x,double y,double r) {
/*代码省略 */
}
}
public class V1Drawing extends Drawing {
public void drawLine(double xl,double yl,double x2,double y2) {
DP1.draw_a_line();
}
public void drawCircle(double x,double y,double r) {
DP1.draw_a_circle(x,y,z);
}
}
public class V2Drawing extends Drawing {
public void drawLine(double xl,double yl,double x2,double y2){
DP2.drawLine();
}
public void drawCircle(double x,double y,double r){
DP2.drawCircle(x,y,z);
}
}
public abstract class Shape {
protected Drawing _dp;
public abstract void draw();
Shape(Drawing dp) {
_dp = dp;
}
public void drawLine(double xl,double yl,double x2,double y2) {
dp.drawLine(xl,y1,x2,y2);
}
public void drawcircle (double x,double y,double r) {
dp.drawcircle (x,y,r);
}
}
public class Rectangle extends Shape {
private double _xl,_x2,_yl,_y2;
public Rectangle(Drawing dp,double xl,double yl,double x2,double y2){
/*代码省略 */
}
public void draw(){
/*代码省略 */
}
}
public class Circle extends Shape {
private double _x,_y,_r;
public Circle(Drawing dp,double x,double y,double r){
/*代码省略去 */
}
public void draw() {
drawcircle(_x,_y,_r);
}
}