设计模式「通关指南」

设计模式通关指南作业一 小王为某管理信息系统的用户管理模块设计了如图所示接口。 1)请你从面向对象设计原则的角度详细分析小王的设计存在什么问题? 2)请你采用

设计模式通关指南

作业一

小王为某管理信息系统的用户管理模块设计了如图所示接口。

1)请你从面向对象设计原则的角度详细分析小王的设计存在什么问题?

2)请你采用面向对象方法帮小王重新设计,使得新设计能够符合面向对象设计原则。简要说明你的设计思想,画出UML类图。

该设计违背了接口隔离原则和单一职责原则。

该接口进行重构设计,将其中的一些方法封装在两个不同的接口中,确保每一个接口使用起来都较为方便。如下面两种重构方案皆可。

客户请小王编写一个从键盘读入字符并输出到打印机的程序。小王使用结构化的设计方法,编写了如下代码。该程序包含3个子程序,Copy子程序从ReadKeyboard子程序中获取字符,并把字符传递给WritePrinter子程序。几个月后,客户说有时希望Copy程序能从纸带读入机中读入字符。并且,在未来可能还会从其它种类的输入设备中读入字符,也可能输出到其它种类的输出设备。小王希望他写出的代码既能满足上述要求,又不用每次都改写Copy的实现。

1)请你从面向对象设计原则的角度分析小王原来的设计存在什么问题?

2)请你采用面向对象方法帮小王重新设计Copy函数,添加必要的类,使得新设计能够满足小王的愿望。简要说明你的设计思想,给出实现代码。

void Copy( ) {
   int c;
   while ((c=ReadKeyboard( )) != EOF))   //EOF为宏定义的终结字符
   WritePrinter(c);
}

小王原来的设计中,高层模块依赖于低层模块,违背了依赖倒置原则。

对该设计进行重构,在高层模块与低层模块之间,引入一个抽象接口层,使得高层模块不直接依赖低层模块,而是依赖抽象接口层,同时,低层模块也依赖(继承或实现)抽象接口。

class Reader
{
public:
  virtual int read()=0;
};
class KeyboardReader: public Reader
{
public:
  virtual int read() { return ReadKeyboard(); }
};
class Writer
{
public:
  virtual int write(int ch)=0;
}
class PrintWriter: public Writer
{
public:
  virtual int write(int ch) { return WritePrinter(ch); }
}
KeyboardReader DefaultReader;
PrintWriter DefaultWriter;
void Copy(Reader& reader=DefaultReader, Writer& writer=DefaultWriter)
{
   int c;
   while ((c=reader.read()) != EOF))
   writer.wirte(c);
}

一个开宝箱游戏的基本描述为:游戏中有多种类型的人物(Role),如战士(Solider)、魔法师(Mage)等,主角的类型只能选择其中一种,且游戏中不再更改。游戏中还有各种宝箱(Box),如装有不同数目金钱的宝箱、装有毒物的宝箱等。当任一种类型的主角打开装有金钱的宝箱时,宝箱中的金钱会增加给主角,同时宝箱的金钱数目变成0;当战士打开装有毒物的宝箱时,战士的生命值(HP)会减少10%,但金钱(Money)增加20%;当魔法师打开装有毒物的宝箱时,魔法师的生命值(HP)会减少30%,但金钱(Money)增加40% 。请根据上述描述,给出相应类的设计并完整实现,要求你的设计应具有良好的扩展性,如增加新角色类型及箱子种类时,不需要修改已有的设计及实现。

class Box;
class Role {
public:
    Role(int theMoney,int theHP):money(theMoney),hp(theHP) { }
    virtual ~Role( ) {}
    int GetMoney( ) const { return money;}
    void SetMoney(int m) { money = m; }
    void Open (Box& aBox) { aBox.BeOpened(*this); }
    virtual void PoisonHurt( ) = 0;
protected:
    int money;
    int hp;
};
class Solider:public Role {
public:
    Solider(int theMoney,int theHP):Role(theMoney,theHP) { }
    virtual void PoisonHurt( ) {
       hp *=0.9;
       money *=1.2;
    }
};
class Mage:public Role {
public:
    Mage (int theMoney,int theHP):Role(theMoney,theHP) { }
    virtual void PoisonHurt( ) {
       hp *=0.7;
       money *=1.4;
    }
};
class Box {
public:
   virtual ~Box( ) {}
   virtual void BeOpened(Role& role) = 0;
};
class MoneyBox:public Box {
public:
   MoneyBox(int m):boxMoney(m) { }
   virtual void BeOpened(Role& role) {
      role.SetMoney(role.GetMoney( ) + boxMoney );
      boxMoney = 0;
   }
protected:
   int boxMoney; 
};
class PoisonBox:public Box {
public:
    virtual void BeOpened(Role& role) { role. PoisonHurt ( ); }
};

给出适当的类设计和相应的代码: 有一个只能放进不能取出的盒子, 最多可放8个水果, 不一定一天放入。水果只是苹果和桔子两种, 它们放入盒子前的原始重量分别为50和30, 放入盒子后, 由于丢失水分, 它们的重量减轻, 苹果和桔子每天分别减轻4和3, 直到达到各自原始重量的3/5后, 不再减轻重量。盒子的功能有: 输出盒子中苹果的数量; 输出盒子中桔子的数量; 输出一天来盒子中水果减轻的总重量; 输出当前水果的总重量。

class Fruit
{
public:
    Fruit(int mMax =0,int mMin=0,int mLose = 0,int mW = 0)
        :mMaxWeight(mMax),mMinWeight(mMin),mLoseWeight(mLose),mWeigth(mW) {}
    virtual ~Fruit() {}

    virtual Fruit * Clone( ) const = 0;
    virtual int ReduceWeight( );
    virtual int  Weight( ) const;
protected:
    int   mMaxWeight;
    int   mMinWeight;
    int   mLoseWeight;
    int   mWeight;
};

int Fruit::ReduceWeight( )
{
        int newWeight = mWeight - mLoseWeight;
        if (newWeight < mMinWeight )
            newWeight = mMinWeight;
        int reduce =  mWeight - newWeight;
        mWeight = newWeight;
        return reduce;
}

int  Fruit::Weight( ) const
{
  return  mWeight;
}

class Apple:public Fruit
{
public:
    Apple():Fruit(50,50*3/5,4,50) { }
    virtual ~Apple( ) {}
    virtual Apple * Clone() const
        { return new Apple(*this); }

    // other
};

class Orange:public Fruit
{
public:
    Orange():Fruit(30,30*3/5,3,30) { }
    virtual ~Orange( ) {}
    virtual Orange * Clone() const
        { return new Orange(*this); }

    // other
};

class Box
{
public:
    Box():count(0) {for(int i=0;i<8;i++) fruit[i]=0;}
    ~Box() {for(int i=0;i<8;i++) delete fruit[i];}
    void AddFruit(Fruit& one)     //放入一个水果
    {

        if (count<8) 
          fruit[count++]=one.Clone();
    }

    int  ApplesNum() const
    {
        int num=0;
        for(int i=0;i<8;i++) {
            Apple * p=dynamic_cast<Apple *>(fruit[i]);
            if (p)
                ++num;
        }
        return num;
    }
    int  OrangesNum() const
    {
        int num=0;
        for(int i=0;i<8;i++) {
            Orange * p=dynamic_cast<Orange *>(fruit[i]);
            if(p)    
              ++num;
        }
        return num;
    }
    int  PassOneDay()  //一天来失去的总重量
    {
        int num=0;
        for(int i=0;i<8;i++)
            if(fruit[i])
                num+=fruit[i]->ReduceWeight();
        return num;
    }
    int  TotalWeight() const
    {
        int num=0;
        for(int i=0;i<8;i++)
            if(fruit[i])
                num+=fruit[i]->Weight();
        return num;
    }
    void Show() const
    {
        cout<<"盒子里共有苹果  ="<<ApplesNum()<<endl;
        cout<<"盒子里共有桔子  ="<<OrangesNum()<<endl;
        cout<<"一天来共失去重量="<<PassOneDay()<<endl;
        cout<<"当前水果的总重量="<<TotalWeight()<<endl;
        cout<<endl;
    }
private:
    Fruit * fruit[8];
    int     count;
};
int main(int argc, char* argv[])
{
    Box aBox;

    Apple a1,a2,a3;

    cout<<"第一天放入一个苹果"<<endl;
    aBox.AddFruit(a1);
    aBox.Show();

    cout<<"第二天又放入一个苹果"<<endl;
    aBox.AddFruit(a2);
    aBox.Show();

    Orange o1,o2;
    cout<<"第三天又放入两个桔子"<<endl;
    aBox.AddFruit(o1);
    aBox.AddFruit(o2);
    aBox.Show();

    cout<<"第四天又放入一个苹果"<<endl;
    aBox.AddFruit(a3);
    aBox.Show();

    return 0;
}

当把下面程序交给用户试用时, 针对函数f, 用户提出了一项新的要求: 当condition为100时, 依次执行b的成员函数g1( )和g2( )。经过进一步了解, 小王获悉: 以后可能还要增加处理condition的值是其它数值时的情况, 但这些需要分别处理的不同条件值的个数肯定不多。小王希望他写出的代码既能满足上述要求, 又不用每次都改写f的代码。请你帮小王重新设计, 使得新设计能够满足小王的愿望。简要说明你的设计思想, 给出实现代码。

class B {
public: 
   B(int n):data(n) { }
   int Data( ) const { return data; }
   void g1( );
   void g2( );
   void g3( );
private:  
   const int data;
};
void f( B& b ) {
   int condition = b.Data( );           
   if(condition == 1) { b.g1( ); }
   else if(condition == 5) { b.g2( ); }
   else if(condition == 9) { b.g3( ); }
}
class B {
public: 
    B(int n):data(n) {}
    int Data( ) const {return data;}
    void g1( ) { cout<<"g1"<<endl; }
    void g2( ) { cout<<"g2"<<endl; }
    void g3( ) { cout<<"g3"<<endl; }
	virtual void g()=0;
private:  
    const int data;
};

class B1:public B
{
public:
	B1():B(1){}
	virtual void g()
	{
		g1();
	}
};

class B5:public B
{
public:
	B5():B(5){}
	virtual void g()
	{
		g2();
	}
};

class B9:public B
{
public:
	B9():B(9){}
	virtual void g()
	{
		g3();
	}
};

class B100:public B
{
public:
	B100():B(100){}
	virtual void g()
	{
		g1();
		g2();
	}
};

void f( B& b ) {
   b.g();
}

int main()
{
	B1 b1;
	f(b1);
	B5 b5;
	f(b5);
	B9 b9;
	f(b9);
	B100 b100;
	f(b100);
	return 0;
}

作业二

小王正在编写一个简单的计算器程序,要求输入两个整数和运算符号(加、减、乘、除),输出计算结果。小王用面向过程方法编写了下面的代码。请采用面向对象方法通过恰当的设计模式对小王的代码进行重构。请写出你所选择的设计模式,画出类图,并给出核心代码。

int main() {
  int numa,numb; char oper; double result;
  cin>>numa>>numb;  cin>>oper;
  switch(oper) {
    case '+': result=numa+numb; break;
    case '-': result=numa-numb; break;
    case '*': result=numa*numb; break;
    case '/': result=numa/(double)numb; break;
  }
  cout<<result<<endl;
  return 0;
}

简单工厂模式

abstract class Operation {
    protected int numberA;
    protected int numberB;

    public abstract double getResult();

    public int getNumberA() {
        return numberA;
    }

    public void setNumberA(int numberA) {
        this.numberA = numberA;
    }

    public int getNumberB() {
        return numberB;
    }

    public void setNumberB(int numberB) {
        this.numberB = numberB;
    }
}

class AddOperation extends Operation {

    @Override
    public double getResult() {
        return numberA + numberB;
    }
}

class SubOperation extends Operation {

    @Override
    public double getResult() {
        return numberA - numberB;
    }
}

class MulOperation extends Operation {

    @Override
    public double getResult() {
        return numberA * numberB;
    }
}

class DivOperation extends Operation {

    @Override
    public double getResult() {
        return numberA / (double) numberB;
    }
}

class Calculator {
    public static Operation createOperation(char operator) {
        Operation op = null;
        switch (operator) {
            case '+':
                op = new AddOperation();
                break;
            case '-':
                op = new SubOperation();
                break;
            case '*':
                op = new MulOperation();
                break;
            case '/':
                op = new DivOperation();
                break;
            default:
                System.out.println("非法操作符");
        }
        return op;
    }
}

public class Client {
    public static void main(String[] args) {
        double result;
        Operation op1 = Calculator.createOperation('+');
        op1.setNumberA(5);
        op1.setNumberB(10);
        result = op1.getResult();
        System.out.println(result);
    }
}

请为一校服制造厂编写一个校服生产子系统。该工厂可为多家学校生产校服,包括秋季校服和夏季校服。一套秋季校服含一件长袖上衣和一条秋季长裤,一套夏季校服含一件短袖衬衣、一件短袖T恤、一条夏季长裤和一条短裤。不同学校校服款式不同。请设计一个子系统为三所学校(一中、二中、三中)分别生产秋季校服和夏季校服(均码)。例如,当用户输入“一中+夏季”时,系统就会生产出一套一中夏季校服;当用户输入“一中+秋季”时,系统生产出一套一中秋季校服。请写出你所选择的设计模式,画出类图,并给出核心代码。

抽象工厂模式

interface AbstractFactory {
    public abstract SummerCloth createSummerCloth();
    public abstract FallCloth createFallCloth();
}
class FactoryFirst implements AbstractFactory {

    @Override
    public SummerCloth createSummerCloth() {
        return new SummerClothFirst();
    }

    @Override
    public FallCloth createFallCloth() {
        return new FallClothFirst();
    }
}
class FactorySecond implements AbstractFactory {

    @Override
    public SummerCloth createSummerCloth() {
        return new SummerClothSecond();
    }

    @Override
    public FallCloth createFallCloth() {
        return new FallClothSecond();
    }
}
class FactoryThird implements AbstractFactory {

    @Override
    public SummerCloth createSummerCloth() {
        return new SummerClothThird();
    }

    @Override
    public FallCloth createFallCloth() {
        return new FallClothThird();
    }
}
interface SummerCloth {
    public abstract void display();
}
class SummerClothFirst implements SummerCloth {

    @Override
    public void display() {
        System.out.println("一中夏季校服");
    }
}
class SummerClothSecond implements SummerCloth {

    @Override
    public void display() {
        System.out.println("二中夏季校服");
    }
}
class SummerClothThird implements SummerCloth {

    @Override
    public void display() {
        System.out.println("三中夏季校服");
    }
}
interface FallCloth {
    public abstract void display();
}
class FallClothFirst implements FallCloth {

    @Override
    public void display() {
        System.out.println("一中秋季校服");
    }
}
class FallClothSecond implements FallCloth {

    @Override
    public void display() {
        System.out.println("二中秋季校服");
    }
}
class FallClothThird implements FallCloth {

    @Override
    public void display() {
        System.out.println("三中秋季校服");
    }
}
public class Client {
    public static void main(String[] args) {
        AbstractFactory f1, f2, f3;
        f1 = new FactoryFirst();
        f2 = new FactorySecond();
        f3 = new FactoryThird();
        SummerCloth c1, c2;
        FallCloth c3;
        c1 = f1.createSummerCloth();
        c1.display();
        c2 = f2.createSummerCloth();
        c2.display();
        c3 = f3.createFallCloth();
        c3.display();
    }
}

小王正在设计一个导出数据的应用框架。客户要求:导出数据可能存储成不同的文件格式,例如:文本格式、数据库备份形式、Excel格式、Xml格式等等,并且,不管什么格式,导出数据文件都分成三个部分,分别是文件头、文件体和文件尾,在文件头部分,需要描述如下信息:分公司或门市点编号、导出数据的日期,对于文本格式,中间用逗号分隔,在文件体部分,需要描述如下信息:表名称、然后分条描述数据,对于文本格式,表名称单独占一行,数据描述一行算一条数据,字段间用逗号分隔,在文件尾部分,需要描述如下信息:输出人。请写出你所选择的设计模式,画出类图,并给出核心代码。

建造者模式

class File {
    private String head;
    private String body;
    private String tail;

    public String getHead() {
        return head;
    }

    public void setHead(String head) {
        this.head = head;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getTail() {
        return tail;
    }

    public void setTail(String tail) {
        this.tail = tail;
    }
}
abstract class Builder {
    protected File file = new File();
    public File getFile() {
        return file;
    }
    public abstract void buildHead();
    public abstract void buildBody();
    public abstract void buildTail();
}
class XmlBuilder extends Builder {
    @Override
    public void buildHead() {
       file.setHead("xml文件头");
    }

    @Override
    public void buildBody() {
       file.setBody("xml文件体");
    }

    @Override
    public void buildTail() {
        file.setTail("xml文件尾");
    }
}
class TextBuilder extends Builder {
    @Override
    public void buildHead() {
        file.setHead("文本文件头");
    }

    @Override
    public void buildBody() {
        file.setBody("文本文件体");
    }

    @Override
    public void buildTail() {
        file.setTail("文本文件尾");
    }
}
class DBBuilder extends Builder {
    @Override
    public void buildHead() {
        file.setHead("数据库备份文件头");
    }

    @Override
    public void buildBody() {
        file.setBody("数据库备份文件体");
    }

    @Override
    public void buildTail() {
        file.setTail("数据库备份文件尾");
    }
}
class ExcelBuilder extends Builder {
    @Override
    public void buildHead() {
        file.setHead("Excel文件头");
    }

    @Override
    public void buildBody() {
        file.setBody("Excel文件体");
    }

    @Override
    public void buildTail() {
        file.setTail("Excel文件尾");
    }
}
class Director {
    private Builder builder;

    public void setBuilder(Builder builder) {
        this.builder = builder;
    }
    public File construct() {
        File file = null;
        builder.buildHead();
        builder.buildBody();
        builder.buildTail();
        file = builder.getFile();
        return file;
    }
}
public class Client {
    public static void main(String[] args) {
        Director director = new Director();
        Builder xmlBuilder;
        xmlBuilder = new XmlBuilder();
        director.setBuilder(xmlBuilder);
        File file = director.construct();
        System.out.println("xml格式组成:");
        System.out.println(file.getHead());
        System.out.println(file.getBody());
        System.out.println(file.getTail());
    }
}
/*
xml格式组成:
xml文件头
xml文件体
xml文件尾
*/

在下面的TicketMaker类(见下表)中,每次调用getNextTicketNumber方法都会返回1000,1001,1002…的数列。我们可以用它生成票的编号或是其他序列号。在现在该类的实现方式下,我们可以生成多个该类的实例。请修改代码,确保只能生成一个该类的实例。

单例模式(双检锁)

public class TicketMaker {
    private TicketMaker(){}
    private int ticket = 1000;
    private static TicketMaker instance = null;
    public static TicketMaker  getInstance() {         // double check lock
        if (instance != null) {
            return instance;
        }
        synchronized (TicketMaker.class) {
            if (instance != null) {
                return instance;
            }
            instance = new TicketMaker();
            return instance;
        }
    }
    public synchronized int getNextTicketNumber() {
            return ticket++;
    }
}

请你按照单例模式的思想,重新实现下面给出的DBConnections类,确保系统中该类的实例对象最多只能存在三个。

class DBConnections {
public:
   DBConnections ( ) { ... } 
   ~ DBConnections ( ) { ... }
   void ConnectionInfo ( ) { ... }
 };

个数限制的单例模式

import java.util.Random;

public class DBConnections {
    private static DBConnections[] connections = {new DBConnections(), new DBConnections(), new DBConnections()};

    private DBConnections() {
    }

    public static DBConnections getInstance() {
        return connections[random()];
    }

    public static int random() {
        Random random = new Random();
        int value = Math.abs(random.nextInt());
        value %= 3;
        return value;
    }

    public static void main(String[] args) {
        DBConnections db1, db2, db3;
        db1 = DBConnections.getInstance();
        db2 = DBConnections.getInstance();
        db3 = DBConnections.getInstance();

        System.out.println(db1 == db2);
        System.out.println(db1 == db3);
    }
}
/*
false
true
*/

作业三

请根据下面的对象适配器类图画出与之相对应的类适配器类图。

开发一个计算机操作系统的线程调度程序,要求实现时间片调度和抢占调度这2种调度算法,支持Windows、Unix和Linux这3个操作系统,并且将来有可能会增加新的调度算法和支持新的操作系统,请选择恰当的设计模式解决该问题,画出类图,写出关键代码。(不考虑线程调度算法的具体代码实现)

桥接模式

interface Algorithm {
    void schedule();
}
abstract class OS {
    protected Algorithm algorithm;
    public void setAlgorithm(Algorithm algorithm) {
        this.algorithm = algorithm;
    }

    public OS(Algorithm algorithm) {
        this.algorithm = algorithm;
    }

    public abstract void work();
}
class Windows extends OS {

    public Windows(Algorithm algorithm) {
        super(algorithm);
    }

    @Override
    public void work() {
        System.out.print("Windows: ");
        algorithm.schedule();
    }
}
class Unix extends OS {

    public Unix(Algorithm algorithm) {
        super(algorithm);
    }

    @Override
    public void work() {
        System.out.print("Unix: ");
        algorithm.schedule();
    }
}
class Linux extends OS {

    public Linux(Algorithm algorithm) {
        super(algorithm);
    }

    @Override
    public void work() {
        System.out.print("Linux: ");
        algorithm.schedule();
    }
}
class TimeSlice implements Algorithm {

    @Override
    public void schedule() {
        System.out.println("时间片调度");
    }
}
class Preemptive implements Algorithm {
    @Override
    public void schedule() {
        System.out.println("抢占调度");
    }
}

public class Client {
    public static void main(String[] args) {
        OS os1, os2, os3;
        Algorithm a1, a2;
        a1 = new TimeSlice();
        a2 = new Preemptive();
        os1 = new Windows(a1);
        os2 = new Unix(a1);
        os3 = new Linux(a2);
        os1.work();
        os2.work();
        os3.work();
    }
}
// Windows: 时间片调度
// Unix: 时间片调度
// Linux: 抢占调度

小王为某五星级酒店开发点餐系统。该酒店为满足客户需要,会在不同的时段提供多种不同的餐饮,其菜单的结构图如图所示。

请你采用面向对象方法通过恰当的设计模式帮助小王对上述菜单进行设计。

组合模式

import java.util.ArrayList;
import java.util.List;

abstract class Component {
    protected String name;

    public Component(String name) {
        this.name = name;
    }
    public abstract void add(Component c);
    public abstract void remove(Component c);
    public abstract void display();
}
class Dish extends Component {

    public Dish(String name) {
        super(name);
    }

    @Override
    public void add(Component c) {
        System.out.println("非法操作");
    }

    @Override
    public void remove(Component c) {
        System.out.println("非法操作");
    }

    @Override
    public void display() {
        System.out.println(name);
    }
}
class Menu extends Component {
    private List<Component> list;
    public Menu(String name) {
        super(name);
        this.list = new ArrayList<>();
    }

    @Override
    public void add(Component c) {
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        list.remove(c);
    }

    @Override
    public void display() {
        System.out.println(name);
        for (Component c : list) {
            c.display();
        }
    }
}

public class Client {
    public static void main(String[] args) {
        Component m1, m2, m3, m4, m5, d1, d2, d3, d4, d5, d6, d7, d8;
        m1 = new Menu("所有菜单");
        m2 = new Menu("煎饼屋菜单");
        m3 = new Menu("餐厅菜单");
        m4 = new Menu("咖啡厅菜单");
        m5 = new Menu("甜点菜单");
        d1 = new Dish("菜式1");
        d2 = new Dish("菜式2");
        d3 = new Dish("菜式m");
        d4 = new Dish("菜式n");
        d5 = new Dish("菜式u");
        d6 = new Dish("菜式y");
        d7 = new Dish("菜式r");
        d8 = new Dish("菜式t");
        m1.add(m2);
        m1.add(m3);
        m1.add(m4);
        m2.add(d1);
        m2.add(d2);
        m2.add(d3);
        m3.add(d4);
        m3.add(m5);
        m5.add(d5);
        m5.add(d6);
        m4.add(d7);
        m4.add(d8);
        m1.display();
    }
}
/*
所有菜单
煎饼屋菜单
菜式1
菜式2
菜式m
餐厅菜单
菜式n
甜点菜单
菜式u
菜式y
咖啡厅菜单
菜式r
菜式t
*/

某饮料店卖饮料时,可以根据顾客的要求在饮料中加入各种配料,饮料店会根据顾客所选的饮料种类和所加入的配料来计算价格。饮料店所供应的部分饮料及配料的种类和价格如下表所示。请你选择恰当的设计模式,为该饮料店开发一个计算饮料价格的程序,要求给出设计思路,画出类图,并写出关键代码。

装饰模式

abstract class Beverage {
    public abstract double getPrice();
    public abstract String getDescription();
}
class MilkTea extends Beverage {

    @Override
    public double getPrice() {
        return 8;
    }

    @Override
    public String getDescription() {
        return "奶茶";
    }
}
class MilkShake extends Beverage {

    @Override
    public double getPrice() {
        return 9;
    }

    @Override
    public String getDescription() {
        return "奶昔";
    }
}
class Coffee extends Beverage {

    @Override
    public double getPrice() {
        return 10;
    }

    @Override
    public String getDescription() {
        return "咖啡";
    }
}
class Condiment extends Beverage {
    private Beverage beverage;

    public Condiment(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public double getPrice() {
        return beverage.getPrice();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription();
    }
}
class Strawberry extends Condiment {

    public Strawberry(Beverage beverage) {
        super(beverage);
    }

    @Override
    public double getPrice() {
        return super.getPrice() + 2;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + "加草莓";
    }
}
class Pudding extends Condiment {

    public Pudding(Beverage beverage) {
        super(beverage);
    }

    @Override
    public double getPrice() {
        return super.getPrice() + 3;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + "加布丁";
    }
}
class Cheese extends Condiment {

    public Cheese(Beverage beverage) {
        super(beverage);
    }

    @Override
    public double getPrice() {
        return super.getPrice() + 4;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + "加芝士雪酪";
    }
}
public class Client {
    public static void main(String[] args) {
        String description;
        double price;
        Beverage beverage;

        beverage = new Coffee();
        description = beverage.getDescription();
        price = beverage.getPrice();
        System.out.println("饮料:" + description);
        System.out.println("价格:" + price);
        System.out.println("---------------------");

        Beverage beverage1;
        beverage1 = new Strawberry(beverage);
        description = beverage1.getDescription();
        price = beverage1.getPrice();
        System.out.println("饮料:" + description);
        System.out.println("价格:" + price);
        System.out.println("---------------------");

        Beverage beverage2;
        beverage2 = new Pudding(beverage1);
        description = beverage2.getDescription();
        price = beverage2.getPrice();
        System.out.println("饮料:" + description);
        System.out.println("价格:" + price);
        System.out.println("---------------------");
    }
}
/*
饮料:咖啡
价格:10.0
---------------------
饮料:咖啡加草莓
价格:12.0
---------------------
饮料:咖啡加草莓加布丁
价格:15.0
---------------------
*/

开发一个系统帮助业务部门实现灵活的奖金计算。对于普通员工,主要有个人当月业务奖金、个人当月回款奖金等,对于部门经理,除了有普通员工的奖金外,还有团队当月业务奖金等。目前各奖金类别的计算规则如下:

个人当月业务奖金 = 个人当月销售额 * 3%

个人当月回款奖金 = 个人当月回款额 * 0.1%

团队当月业务奖金 = 团队当月销售额 * 1%

考虑到业务部门要通过调整奖金计算方式来激励士气,系统应灵活地适应各种需求变化,例如,将来可能会增加个人业务增长奖金、团队当月回款奖金、团队业务增长奖金、团队盈利奖金等奖金类别,也可能增加新的员工岗位,或变更奖金计算规则等。请写出你所选择的设计模式,画出类图,并给出核心代码。

装饰模式

Factory只是用来提供对不同员工每月销售额等信息的查询

import java.util.HashMap;

abstract class Component {
    public abstract double getBonus(String name);
    public abstract String getDes(String name);
}
class Employee extends Component{
    @Override
    public double getBonus(String name) {
        return 0;
    }

    @Override
    public String getDes(String name) {
        return "普通员工";
    }
}
class Manager extends Component{
    @Override
    public double getBonus(String name) {
        return 0;
    }

    @Override
    public String getDes(String name) {
        return "经理";
    }
}
class Decorator extends Component {
    private Component c;

    public Decorator(Component c) {
        this.c = c;
    }

    @Override
    public double getBonus(String name) {
        return c.getBonus(name);
    }

    @Override
    public String getDes(String name) {
        return c.getDes(name);
    }
}
class PersonBusiness extends Decorator {

    public PersonBusiness(Component c) {
        super(c);
    }

    @Override
    public double getBonus(String name) {
        return super.getBonus(name) + Factory.getPersonSell(name) * 0.03;
    }

    @Override
    public String getDes(String name) {
        return super.getDes(name) + "获得个人业务奖金";
    }
}
class PersonPayback extends Decorator {

    public PersonPayback(Component c) {
        super(c);
    }

    @Override
    public double getBonus(String name) {
        return super.getBonus(name) + Factory.getPersonPayback(name) * 0.001;
    }

    @Override
    public String getDes(String name) {
        return super.getDes(name) + "获得个人回款奖金";
    }
}
class TeamBusiness extends Decorator {

    public TeamBusiness(Component c) {
        super(c);
    }

    @Override
    public double getBonus(String name) {
        return super.getBonus(name) + Factory.getTeamSell(name) * 0.01;
    }

    @Override
    public String getDes(String name) {
        return super.getDes(name) + "获得团队业务奖金";
    }
}
class Person {
    private String name;
    private double personSell;
    private double personPayback;
    private double teamSell;

    public Person(String name, double personSell, double personPayback, double teamSell) {
        this.name = name;
        this.personSell = personSell;
        this.personPayback = personPayback;
        this.teamSell = teamSell;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPersonSell() {
        return personSell;
    }

    public void setPersonSell(double personSell) {
        this.personSell = personSell;
    }

    public double getPersonPayback() {
        return personPayback;
    }

    public void setPersonPayback(double personPayback) {
        this.personPayback = personPayback;
    }

    public double getTeamSell() {
        return teamSell;
    }

    public void setTeamSell(double teamSell) {
        this.teamSell = teamSell;
    }
}
class Factory {
    private static HashMap<String, Person> persons = new HashMap<>();
    private Factory(){}
    public static void addPerson(String name, Person p) {
        persons.put(name, p);
    }
    public static double getPersonSell(String name) {
        if (persons.containsKey(name)) {
            Person p = persons.get(name);
            return p.getPersonSell();
        } else {
            return 0;
        }
    }
    public static double getPersonPayback(String name) {
        if (persons.containsKey(name)) {
            Person p = persons.get(name);
            return p.getPersonPayback();
        } else {
            return 0;
        }
    }
    public static double getTeamSell(String name) {
        if (persons.containsKey(name)) {
            Person p = persons.get(name);
            return p.getTeamSell();
        } else {
            return 0;
        }
    }
}
public class Client {
    public static void main(String[] args) {
        Person p1, p2;
        p1 = new Person("张三", 5000, 1000, 10000);
        p2 = new Person("李四", 10000, 2000, 20000);
        Factory.addPerson("张三", p1);
        Factory.addPerson("李四", p2);
        Component e1, m1, personBusiness, personPayback, teamBusiness;
        String name;

        e1 = new Employee();
        name = p1.getName();
        personBusiness = new PersonBusiness(e1);
        personPayback = new PersonPayback(personBusiness);
        System.out.print(name);
        System.out.println(personPayback.getDes(name));
        System.out.println(personPayback.getBonus(name));

        m1 = new Manager();
        name = p2.getName();
        personBusiness = new PersonBusiness(m1);
        personPayback = new PersonPayback(personBusiness);
        teamBusiness = new TeamBusiness(personPayback);
        System.out.print(name);
        System.out.println(teamBusiness.getDes(name));
        System.out.println(teamBusiness.getBonus(name));
    }
}
/*
张三普通员工获得个人业务奖金获得个人回款奖金
151.0
李四经理获得个人业务奖金获得个人回款奖金获得团队业务奖金
502.0
*/

作业四

某学校的差旅费报销制度规定,要根据不同的报销金额,由不同的领导审批,1万元以下科长审批,1万元至5万元之间处长审批,5万元至10万元之间副校长审批,10万元以上校长审批。最常用的编程思想是采用条件语句进行判断,但是随着差旅费报销制度的逐渐完善,可能需要判断的条件会越来越多,可能处理的逻辑也更加复杂,代码将变得难以维护。请选择恰当的设计模式解决该问题,画出类图,写出关键代码。

职责链模式

package TestE;

abstract class Leader {
    protected Leader successor;
    protected String name;

    Leader(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setLeader(Leader leader) {
        this.successor = leader;
    }

    public abstract void handleRequest(double money);
}

class SectionChief extends Leader {

    SectionChief(String name) {
        super(name);
    }

    @Override
    public void handleRequest(double money) {
        if (money < 1) {
            System.out.println("科长" + this.getName() + "审批金额为" + money + "万元的报销");
        } else {
            this.successor.handleRequest(money);
        }
    }
}

class Director extends Leader {

    Director(String name) {
        super(name);
    }

    @Override
    public void handleRequest(double money) {
        if (money < 5) {
            System.out.println("处长" + this.getName() + "审批金额为" + money + "万元的报销");
        } else {
            this.successor.handleRequest(money);
        }
    }
}

class ViceChancellor extends Leader {

    ViceChancellor(String name) {
        super(name);
    }

    @Override
    public void handleRequest(double money) {
        if (money < 10) {
            System.out.println("副校长" + this.getName() + "审批金额为" + money + "万元的报销");
        } else {
            this.successor.handleRequest(money);
        }
    }
}

class Chancellor extends Leader {

    Chancellor(String name) {
        super(name);
    }

    @Override
    public void handleRequest(double money) {
        System.out.println("校长" + this.getName() + "审批金额为" + money + "万元的报销");
    }
}

public class Client {
    public static void main(String[] args) {
        Leader sectionChief = new SectionChief("张三");
        Leader director = new Director("李四");
        Leader viceChancellor = new ViceChancellor("王五");
        Leader chancellor = new Chancellor("赵六");
        sectionChief.setLeader(director);
        director.setLeader(viceChancellor);
        viceChancellor.setLeader(chancellor);
        sectionChief.handleRequest(0.1);
        sectionChief.handleRequest(2);
        sectionChief.handleRequest(6);
        sectionChief.handleRequest(11);
    }
}
//        科长张三审批金额为0.1万元的报销
//        处长李四审批金额为2.0万元的报销
//        副校长王五审批金额为6.0万元的报销
//        校长赵六审批金额为11.0万元的报销

小王准备使用面向对象的方法设计一个快餐店的简单游戏,游戏中有顾客、服务员、菜品和厨师。每个顾客都有一个服务员帮助点菜,并且可以点多个菜;每道菜都由指定厨师制作,不同的菜可能由不同的厨师制作;顾客跟服务员点完菜后,服务员通知后厨做菜。请你针对上面的描述,帮助小王选择合适的设计模式进行设计。1)简要说明你的设计思路和选择的模式。2)给出你设计的UML类图和实现代码。

命令模式

顾客是请求发送者,服务员是命令队列,菜品是命令,不同的菜品是具体命令,使用命令队列

import java.util.ArrayList;

class Customer {
    private Waiter waiter;

    public Customer(Waiter waiter) {
        this.waiter = waiter;
    }

    public void call() {
        System.out.println("顾客完成点菜");
        waiter.execute();
    }

    public void order(Dish command) {
        waiter.attach(command);
    }

    public void removeOrder(Dish command) {
        waiter.detach(command);
    }
}

class Waiter {
    private ArrayList<Dish> commands = new ArrayList<>();
    private String name;

    public Waiter(String name) {
        this.name = name;
    }

    public void execute() {
        System.out.println("服务员" + name + "通知后厨做菜");
        for (Dish command : commands) {
            command.cook();
        }
    }

    public void attach(Dish command) {
        commands.add(command);
    }

    public void detach(Dish command) {
        commands.remove(command);
    }
}

abstract class Dish {

    public abstract void cook();
}

class Dish1 extends Dish {
    private Cook cook = new Cook("张三");
    private String name = "鱼香肉丝";

    @Override
    public void cook() {
        cook.make(name);
    }
}
class Dish2 extends Dish {
    private Cook cook = new Cook("张三");
    private String name = "炒土豆丝";

    @Override
    public void cook() {
        cook.make(name);
    }
}
class Dish3 extends Dish {
    private Cook cook = new Cook("李四");
    private String name = "西红柿炒鸡蛋";

    @Override
    public void cook() {
        cook.make(name);
    }
}
class Cook {
    private String name;

    public Cook(String name) {
        this.name = name;
    }

    public void make(String dishName) {
        System.out.println("厨师" + name + "做了" + dishName);
    }
}

public class Client {
    public static void main(String[] args) {
        Waiter waiter = new Waiter("小三");
        Customer customer = new Customer(waiter);
        Dish dish1, dish2, dish3;
        dish1 = new Dish1();
        dish2 = new Dish2();
        dish3 = new Dish3();
        customer.order(dish1);
        customer.order(dish2);
        customer.order(dish3);
        customer.call();
    }
}
/*
顾客完成点菜
服务员小三通知后厨做菜
厨师张三做了鱼香肉丝
厨师张三做了炒土豆丝
厨师李四做了西红柿炒鸡蛋
*/

小明正在开发一个病房呼叫应答仿真系统。系统中每个病房配备一个呼叫按钮和一个呼叫显示应答器,疗区大厅配备一个显示应答器和一个语音播报器。假设,按下001号病房的呼叫按钮后,那么,所有的呼叫显示应答器都会显示发出呼叫的病房号001,大厅同时语音播报该病房号001。当医护人员按下任意一处的呼叫显示应答器的应答按钮后,所有呼叫显示应答器停止显示该房间号,大厅也停止语音播报。请用恰当的设计模式实现该系统,画出类图,给出核心代码。

中介者模式,不能是观察者模式,因为观察者模式的主动方是 Subject,中介者的主动方是同事类。

import java.util.ArrayList;

abstract class AbstractHospital {
    public abstract void register(Member member);
    public abstract void call(String id);
    public abstract void stopShow();
}

class Hospital extends AbstractHospital {
    private ArrayList<Member> members = new ArrayList<>();
    @Override
    public void register(Member member) {
        members.add(member);
        member.setHospital(this);
    }

    @Override
    public void call(String id) {
        for (Member m : members) {
            m.show(id);
        }
    }

    @Override
    public void stopShow() {
        for (Member m : members) {
            m.response();
        }
    }
}

abstract class Member {
    protected String name;
    protected AbstractHospital hospital;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public AbstractHospital getHospital() {
        return hospital;
    }

    public void setHospital(AbstractHospital hospital) {
        this.hospital = hospital;
    }

    public Member(String name) {
        this.name = name;
    }

    public void show(String id) {
        System.out.println(name + "呼叫显示应答器显示:" + id + "号病床呼叫");
    }
    public abstract void call();
    public abstract void response();
    public void stopShow() {
        hospital.stopShow();
    }
}

class Ceil extends Member {

    public Ceil(String name) {
        super(name);
    }

    @Override
    public void call() {
        hospital.call(name);
    }

    @Override
    public void response() {
        System.out.println(name + "呼叫显示应答器停止显示");
    }
}

class Lobby extends Member {

    public Lobby(String name) {
        super(name);
    }

    public void show(String id) {
        System.out.println(name + "呼叫显示应答器显示:" + id + "号病床呼叫");
        System.out.println(name + "语言播报" + id + "号病床");
    }

    @Override
    public void call() {
        System.out.println("大厅不能呼叫");
    }

    @Override
    public void response() {
        System.out.println(name + "呼叫显示应答器停止显示");
        System.out.println(name + "停止播报");
    }

}

public class Client {
    public static void main(String[] args) {
        AbstractHospital hospital;
        Member ceil1, ceil2, ceil3, lobby;
        hospital = new Hospital();
        ceil1 = new Ceil("病房1");
        ceil2 = new Ceil("病房2");
        ceil3 = new Ceil("病房3");
        lobby = new Lobby("大厅");
        hospital.register(ceil1);
        hospital.register(ceil2);
        hospital.register(ceil3);
        hospital.register(lobby);
        ceil1.call();
        ceil2.stopShow();
    }
}
/*
病房1呼叫显示应答器显示:病房1号病床呼叫
病房2呼叫显示应答器显示:病房1号病床呼叫
病房3呼叫显示应答器显示:病房1号病床呼叫
大厅呼叫显示应答器显示:病房1号病床呼叫
大厅语言播报病房1号病床
病房2应答
病房1呼叫显示应答器停止显示
病房2呼叫显示应答器停止显示
病房3呼叫显示应答器停止显示
大厅呼叫显示应答器停止显示
大厅停止播报
*/

小王正在为某公司设计开发一套物业租赁管理系统,该公司有多种类型的物业,如公寓、商铺等,并且在将来可能会增加新的物业类型,如别墅、车库等;公司的经纪每租出一个物业,主管就会收到相应的租赁信息。请你针对上面的描述,帮助小王选择合适的设计模式进行设计。1)简要说明你的设计思路和选择的模式。2)给出你设计的UML类图和实现代码。

对于“该公司有多种类型的物业,如公寓、商铺等,并且在将来可能会增加新的物业类型,如别墅、车库等;”可以采用工厂方法模式进行设计,对于“公司的经纪每租出一个物业,主管就会收到相应的租赁信息”可以采用观察者模式进行设计

import java.util.ArrayList;
import java.util.List;

class House {
    protected String id;
    protected double price;
    protected int status;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getStatus() {
        return status;
    }

    public List<Stakeholder> getStakeholders() {
        return stakeholders;
    }

    public void setStakeholders(List<Stakeholder> stakeholders) {
        this.stakeholders = stakeholders;
    }

    protected List<Stakeholder> stakeholders;
    public void setStatus(int status) {
        this.status = status;
        if (status == 0) {
            for (Stakeholder s : stakeholders) {
                s.response(this);
            }
        }
    }
    public void addStakeholder(Stakeholder sh) {
        stakeholders.add(sh);
    }
}
class Villadom extends House {
}
class Apartment extends House {
}
abstract class Stakeholder {
    public abstract void response(House house);
}
class Manager extends Stakeholder {

    @Override
    public void response(House house) {
        System.out.println("房子" + house.getId() + "已售出,价格为" + house.getPrice());
    }
}
abstract class HouseCreator {
    public abstract House createHouse();
}
class VilladomCreator extends HouseCreator {

    @Override
    public House createHouse() {
        return new Villadom();
    }
}
class ApartmentCreator extends HouseCreator {

    @Override
    public House createHouse() {
        return new Apartment();
    }
}
public class Client {
    public static void main(String[] args) {
        House h1, a1;
        Stakeholder m1, m2, m3;
        HouseCreator c1, c2;
        ArrayList<Stakeholder> stakeholders = new ArrayList<>();
        c1 = new VilladomCreator();
        c2 = new ApartmentCreator();
        h1 = c1.createHouse();
        a1 = c2.createHouse();
        m1 = new Manager();
        m2 = new Manager();
        m3 = new Manager();
        stakeholders.add(m1);
        stakeholders.add(m2);
        stakeholders.add(m3);
        h1.setId("别墅001");
        h1.setPrice(5500000);
        h1.setStakeholders(stakeholders);
        h1.setStatus(1);

        a1.setId("公寓001");
        a1.setPrice(1000);
        a1.setStakeholders(stakeholders);
        a1.setStatus(1);

        h1.setStatus(0);
        a1.setStatus(0);
    }
}
/*
房子别墅001已售出,价格为5500000.0
房子别墅001已售出,价格为5500000.0
房子别墅001已售出,价格为5500000.0
房子公寓001已售出,价格为1000.0
房子公寓001已售出,价格为1000.0
房子公寓001已售出,价格为1000.0
*/

开发一个消防应急响应系统,火灾探测器(FireDetector)发现火灾异常后将自动传递信号给各种响应设备,例如警示灯(WarningLight)将闪烁(flicker())、报警器(Alarm)将发出警报(alarm())、安全逃生门(SecurityDoor)将自动开启(open())、隔离门(InsulatedDoor)将自动关闭(close())等,每一种响应设备的行为由专门的程序来控制。请写出你所选择的设计模式,画出类图,并给出核心代码。

观察者模式和适配器模式

import java.util.ArrayList;

abstract class AbstractDectector {
    protected ArrayList<AbstractEquipment> equipments = new ArrayList<>();

    public abstract void call();

    public abstract void attach(AbstractEquipment equipment);

    public abstract void detack(AbstractEquipment equipment);
}

class FireDectector extends AbstractDectector {
    @Override
    public void call() {
        System.out.println("发现火灾,通知响应设备");
        for (AbstractEquipment equipment : equipments) {
            equipment.response();
        }
    }

    @Override
    public void attach(AbstractEquipment equipment) {
        equipments.add(equipment);
    }

    @Override
    public void detack(AbstractEquipment equipment) {
        equipments.remove(equipment);
    }
}

abstract class AbstractEquipment {
    public abstract void response();
}

class WarningLight {
    public void flicker() {
        System.out.println("警示灯闪烁");
    }
}

class WarningLightAdapter extends AbstractEquipment {
    private WarningLight warningLight;

    public WarningLightAdapter(WarningLight warningLight) {
        this.warningLight = warningLight;
    }

    @Override
    public void response() {
        this.warningLight.flicker();
    }
}

class Alarm {
    public void alarm() {
        System.out.println("报警器发出警报");
    }
}

class AlarmAdatper extends AbstractEquipment {
    private Alarm alarm;

    public AlarmAdatper(Alarm alarm) {
        this.alarm = alarm;
    }

    @Override
    public void response() {
        this.alarm.alarm();
    }
}

class SecurityDoor {
    public void open() {
        System.out.println("安全逃生们开启");
    }
}

class SecurityDoorAtapter extends AbstractEquipment {
    private SecurityDoor door;

    public SecurityDoorAtapter(SecurityDoor door) {
        this.door = door;
    }

    @Override
    public void response() {
        this.door.open();
    }
}

class InsulatedDoor {
    public void close() {
        System.out.println("隔离门自动关闭");
    }
}

class InsulatedDoorAdapter extends AbstractEquipment {
    private InsulatedDoor door;

    public InsulatedDoorAdapter(InsulatedDoor door) {
        this.door = door;
    }

    @Override
    public void response() {
        this.door.close();
    }
}

public class Client {
    public static void main(String[] args) {
        AbstractDectector fireDectector = new FireDectector();
        AbstractEquipment warningLightAdapter, alarmAdatper, securityDoorAtapter, insulatedDoorAdapter;
        WarningLight warningLight = new WarningLight();
        Alarm alarm = new Alarm();
        SecurityDoor securityDoor = new SecurityDoor();
        InsulatedDoor insulatedDoor = new InsulatedDoor();
        warningLightAdapter = new WarningLightAdapter(warningLight);
        securityDoorAtapter = new SecurityDoorAtapter(securityDoor);
        insulatedDoorAdapter = new InsulatedDoorAdapter(insulatedDoor);
        alarmAdatper = new AlarmAdatper(alarm);
        fireDectector.attach(warningLightAdapter);
        fireDectector.attach(securityDoorAtapter);
        fireDectector.attach(insulatedDoorAdapter);
        fireDectector.attach(alarmAdatper);
        fireDectector.call();
    }
}
/*
发现火灾,通知响应设备
警示灯闪烁
安全逃生们开启
隔离门自动关闭
报警器发出警报
*/

小明为某银行开发一个报警系统,该系统功能描述如下,请你帮助小明完成设计,给出设计模式的名称,画出类图,写出关键代码。

状态模式

class Clock {
    private String time;

    public String getTime() {
        return time;
    }
}
class Phone {
    public void callAlarmCenter() {
        System.out.println("呼叫警报中心");
    }
    public void messageAlarmCenter() {
        System.out.println("呼叫警报中心的留言电话");
    }
}
class AlarmCenter {
    public void record() {
        System.out.println("在警报中心记录");
    }
    public void urgentNotify() {
        System.out.println("向警报中心发送紧急事态通知");
    }
}
class AlarmBell {
    private AlarmCenter alarmCenter = new AlarmCenter();

    public void urgentNotify() {
        alarmCenter.urgentNotify();
    }
}
class Vault {
    private State state;
    private Clock clock;
    private AlarmCenter alarmCenter;
    private AlarmBell alarmBell;
    private Phone phone;

    public Vault(Clock clock, AlarmCenter alarmCenter, AlarmBell alarmBell, Phone phone) {
        this.clock = clock;
        this.alarmCenter = alarmCenter;
        this.alarmBell = alarmBell;
        this.phone = phone;
    }

    public Phone getPhone() {
        return phone;
    }

    public void setPhone(Phone phone) {
        this.phone = phone;
    }

    public AlarmBell getAlarmBell() {
        return alarmBell;
    }

    public void setAlarmBell(AlarmBell alarmBell) {
        this.alarmBell = alarmBell;
    }

    public AlarmCenter getAlarmCenter() {
        return alarmCenter;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }
    public void use() {
        this.state.use();
    }
    public void useAlarm() {
        this.state.useAlarm();
    }
    public void usePhone() {
        this.state.usePhone();
    }
}
abstract class State {
    protected Vault vault;
    public abstract void use();

    public State(Vault vault) {
        this.vault = vault;
    }

    public void useAlarm() {
        System.out.println("使用警铃");
        this.vault.getAlarmBell().urgentNotify();
    }

    public abstract void usePhone();
}
class DayState extends State {
    public DayState(Vault vault) {
        super(vault);
    }

    @Override
    public void use() {
        System.out.println("白天使用金库");
        vault.getAlarmCenter().record();
    }

    @Override
    public void usePhone() {
        System.out.println("白天使用电话");
        vault.getPhone().callAlarmCenter();
    }
}
class NightState extends State{
    public NightState(Vault vault) {
        super(vault);
    }

    @Override
    public void use() {
        System.out.println("夜晚使用金库");
        vault.getAlarmCenter().urgentNotify();
    }


    @Override
    public void usePhone() {
        System.out.println("夜晚使用电话");
        vault.getPhone().messageAlarmCenter();
    }
}
public class Client {
    public static void main(String[] args) {
        State dayState, nightState;
        Vault vault = new Vault(new Clock(), new AlarmCenter(), new AlarmBell(), new Phone());
        dayState = new DayState(vault);
        nightState = new NightState(vault);
        vault.setState(dayState);
        System.out.println("白天:");
        vault.use();
        vault.useAlarm();
        vault.usePhone();
        vault.setState(nightState);
        System.out.println("夜晚:");
        vault.use();
        vault.useAlarm();
        vault.usePhone();
    }
}
/*
白天:
白天使用金库
在警报中心记录
使用警铃
向警报中心发送紧急事态通知
白天使用电话
呼叫警报中心
夜晚:
夜晚使用金库
向警报中心发送紧急事态通知
使用警铃
向警报中心发送紧急事态通知
夜晚使用电话
呼叫警报中心的留言电话
*/

小明正在开发一个温度自动调节系统,该系统能够根据用户设置的温度值自动调节温度。当系统开启时,它会读取用户设置的期望温度值T,若当前温度低于T,它将温度提升到T,若当前温度高于T,它将温度降为T。当系统关闭时,它将停止调节温度。当系统开启时,它可以接受温度设置及关闭系统的指令,当系统关闭时,它只接受开启系统的指令。请用恰当的设计模式设计该系统,画出类图,给出核心代码。

状态模式

class TemperatureSystem {
    private AbstractState state = new Shutdown();
    private double T;
    private double nowT;

    public TemperatureSystem(double T, double nowT) {
        this.T = T;
        this.nowT = nowT;
    }

    public double getT() {
        return T;
    }

    public void setT(double t) {
        T = t;
    }

    public void setNowT(double nowT) {
        this.nowT = nowT;
    }

    public double getNowT() {
        return nowT;
    }

    public void open() {
        System.out.println("系统开始工作");
        if (nowT < T) state = new Heating();
        else if (nowT > T) state = new Cooling();
        else System.out.println("系统当前温度等于期望温度,系统关闭");
        state.work(this);
    }

    public void setState(AbstractState state) {
        this.state = state;
    }

    public String getState() {
        return state.getName();
    }

    public void shutdown() {
        setState(new Shutdown());
    }

}

abstract class AbstractState {
    public abstract void work(TemperatureSystem temperatureSystem);
    public abstract String getName();
}

class Shutdown extends AbstractState {
    private String name = "系统关闭状态";

    public String getName() {
        return name;
    }

    @Override
    public void work(TemperatureSystem temperatureSystem) {
        System.out.println("系统关闭,无法工作");
    }
}

class Heating extends AbstractState {
    private String name = "系统加热状态";

    public String getName() {
        return name;
    }

    @Override
    public void work(TemperatureSystem temperatureSystem) {
        while (true) {
            if (temperatureSystem.getNowT() < temperatureSystem.getT()) {
                System.out.println("当前温度是" + temperatureSystem.getNowT() + "小于期望温度" + temperatureSystem.getT() + ",系统加热");
                temperatureSystem.setNowT(temperatureSystem.getNowT() + 1);
            } else if (temperatureSystem.getNowT() > temperatureSystem.getT()) {
                System.out.println("当前温度是" + temperatureSystem.getNowT() + "大于期望温度" + temperatureSystem.getT() + ",系统停止加热,进行降温");
                temperatureSystem.setState(new Cooling());
            } else {
                System.out.println("当前温度等于期望温度,系统关闭");
                temperatureSystem.setState(new Shutdown());
                break;
            }
        }
    }
}

class Cooling extends AbstractState {
    private String name = "系统降温状态";

    public String getName() {
        return name;
    }

    @Override
    public void work(TemperatureSystem temperatureSystem) {
        while (true) {
            if (temperatureSystem.getNowT() > temperatureSystem.getT()) {
                System.out.println("当前温度是" + temperatureSystem.getNowT() + "小于期望温度" + temperatureSystem.getT() + ",系统加热");
                temperatureSystem.setNowT(temperatureSystem.getNowT() - 1);
            } else if (temperatureSystem.getNowT() < temperatureSystem.getT()) {
                System.out.println("当前温度是" + temperatureSystem.getNowT() + "小于期望温度" + temperatureSystem.getT() + ",系统停止降温,进行加热");
                temperatureSystem.setState(new Heating());
            } else {
                System.out.println("当前温度等于期望温度,系统关闭");
                temperatureSystem.setState(new Shutdown());
                break;
            }
        }
    }
}

public class Client {
    public static void main(String[] args) {
        TemperatureSystem system = new TemperatureSystem(20, 15);
        system.shutdown();
        system.open();
    }
}
/*
系统开始工作
当前温度是15.0小于期望温度20.0,系统加热
当前温度是16.0小于期望温度20.0,系统加热
当前温度是17.0小于期望温度20.0,系统加热
当前温度是18.0小于期望温度20.0,系统加热
当前温度是19.0小于期望温度20.0,系统加热
当前温度等于期望温度,系统关闭
*/

小王正在开发一套电影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票打折方式,具体打折方案如下:(1) 学生凭学生证可享受票价7折优惠;(2) 年龄在10周岁及以下的儿童可享受每张票减免15元的优惠(原始票价需大于等于30元);(3) 影院会员卡用户除享受票价半价优惠外还可进行积分,积分累计到一定额度可换取电影院赠送的奖品。该系统在将来可能还要根据需要引入新的打折方式。请你针对上面的描述,帮助小王进行设计,给出设计思路及所采用的设计模式,画出类图,并写出关键代码。

策略模式

class Cinema {
    private Strategy strategy;

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public Cinema(Strategy strategy) {
        this.strategy = strategy;
    }

    public void sell(double price) {
        strategy.sell(price);
    }
}

abstract interface Strategy {
    public void sell(double price);
}

class Student implements Strategy {

    @Override
    public void sell(double price) {
        System.out.println("学生:" + "原价" + price + ",打7折优惠之后票价" + price * 0.7);
    }
}

class Chlid implements Strategy {

    @Override
    public void sell(double price) {
        double origin = price;
        if (price >= 30) {
            price -= 15;
            System.out.println("儿童:" + "原价" + origin + "大于等于30元,减免15元之后票价" + price);
        } else {
            System.out.println("儿童:" + "原价" + origin + "小于30元,按原价售卖");
        }
    }
}
class Member implements Strategy {

    @Override
    public void sell(double price) {
        System.out.println("会员:" + "原价" + price + ",半折优惠之后票价" + price * 0.5 + ",且积分");
    }
}
public class Client {
    public static void main(String[] args) {
        Strategy strategy1, strategy2, strategy3;
        strategy1 = new Student();
        strategy2 = new Chlid();
        strategy3 = new Member();
        Cinema cinema = new Cinema(strategy1);
        cinema.sell(100);
        cinema.setStrategy(strategy2);
        cinema.sell(53);
        cinema.setStrategy(strategy3);
        cinema.sell(87);
    }
}
/*
学生:原价100.0,打7折优惠之后票价70.0
儿童:原价53.0大于等于30元,减免15元之后票价38.0
会员:原价87.0,半折优惠之后票价43.5,且积分
*/

明在使用策略模式进行设计时,发现策略所对应的多个算法在实现上有很多公共功能,请你给出建议帮助小明能更好地实现复用?小明再进一步设计时,又发现这些算法的实现步骤都是一样的,只是在某些局部步骤的实现上有所不同,那么请你再帮帮小明,如何能更好地实现复用?

可以有下面两种思路:一种思路就是把抽象策略的接口改成抽象类,然后在里面实现具体算法的公共功能;另一种思路是给所有的具体策略算法定义一个抽象的父类,让这个父类去实现策略的接口,然后在这个父类里面去实现公共的功能。最好采用第二种,因为:进一步发现“一系列算法的实现步骤都是一样的,只是在某些局部步骤上有所不同”的情况时,就可以在这个抽象类里面定义算法实现的骨架,然后让具体的策略算法去实现变化的部分。上述的结构实际上是策略模式结合模板方法模式,那个抽象类就成了模板方法模式的模板类

请为上海中心大厦设计一个大楼管理系统。大厦由地上118层主楼、5层裙楼和5层地下室组成。大厦分为5大功能区域,包括大众商业娱乐区域,办公区域,企业会馆区域,精品酒店区域和顶部功能体验空间。要求:能够对整幢大厦的管线和房间进行按层查看,比如展示楼房某一层的房间分布及管线状态(注:有埋在地板下面的水平管线,也有垂直管线)。请给出设计思路及所采用的设计模式,画出类图,并写出关键代码。

开放性题目,可使用组合模式、迭代器模式、工厂模式、原型模式等模式

本文使用组合模式

import java.util.ArrayList;

interface Region {
    public void display();

    public void Add(Region r);

    public void Remove(Region r);

    public Region GetChild(int i);
}

class buildingInfo implements Region {
    String room;
    String pipeline;

    public buildingInfo(String room, String pipeline) {
        this.room = room;
        this.pipeline = pipeline;
    }

    public void display() {
        System.out.println("房间分布:" + room + " 管线状态:" + pipeline);
    }

    public void Add(Region r) {
        System.out.println("叶子节点不可添加");
    }

    public void Remove(Region r) {
        System.out.println("叶子节点不可删除");
    }

    public Region GetChild(int i) {
        System.out.println("叶子节点没有子节点");
        return null;
    }

}

class mainbuilding implements Region {

    String name;

    int floorNumber;

    private ArrayList<Region> list = new ArrayList<Region>();

    public mainbuilding(String name, int number) {
        this.name = name;
        this.floorNumber = number;
    }

    public void display() {
        for (int i = 0; i < list.size(); i++) {
            list.get(i).display();
        }
    }

    public void Add(Region r) {
        list.add(r);
    }

    public void Remove(Region r) {
        list.remove(r);
    }

    public Region GetChild(int i) {

        return (Region) list.get(i);
    }
}

public class Client {

    public static void main(String[] args) {
        Region happyroom = new buildingInfo("娱乐房间", "垂直管线");
        Region movieroom = new buildingInfo("电影房间", "垂直管线");
        Region singroom = new buildingInfo("唱歌房间", "垂直管线");
        Region happybuilding = new mainbuilding("娱乐", 35);
        happybuilding.Add(happyroom);
        happybuilding.Add(movieroom);
        happybuilding.Add(singroom);
        System.out.println("查看第35层的房间分布和管线状态:");
        happybuilding.display();
    }
}
/*
查看第35层的房间分布和管线状态:
房间分布:娱乐房间 管线状态:垂直管线
房间分布:电影房间 管线状态:垂直管线
房间分布:唱歌房间 管线状态:垂直管线
*/

历年真题

某台电脑上的Word文档有三种打开方式:桌面双击文档的图标打开、鼠标右键菜单选择打开方式Microsoft Office Word打开、Word菜单命令打开。还有三种保存方式:点击保存、ctrl+s保存、菜单命令保存。请为六种操作编写代码,要求写出你所选择的设计模式,画出类图,并给出核心代码。

策略模式

class Word {
    private OpenCommand o;
    private SaveCommand s;
    public void open() {
        o.execute();
    }
    public void save() {
        s.execute();
    }

    public void setOpenCommand(OpenCommand o) {
        this.o = o;
    }

    public void setSaveCommand(SaveCommand s) {
        this.s = s;
    }
}
interface OpenCommand {
    public abstract void execute();
}
class OpenCommand1 implements OpenCommand {

    @Override
    public void execute() {
        System.out.println("桌面双击文档的图标打开");
    }
}
class OpenCommand2 implements OpenCommand {

    @Override
    public void execute() {
        System.out.println("鼠标右键菜单选择打开方式Microsoft Office Word打开");
    }
}
class OpenCommand3 implements OpenCommand {

    @Override
    public void execute() {
        System.out.println("Word菜单命令打开");
    }
}
interface SaveCommand {
    public abstract void execute();
}
class SaveCommand1 implements SaveCommand {

    @Override
    public void execute() {
        System.out.println("点击保存");
    }
}
class SaveCommand2 implements SaveCommand {

    @Override
    public void execute() {
        System.out.println("ctrl+s保存");
    }
}
class SaveCommand3 implements SaveCommand {

    @Override
    public void execute() {
        System.out.println("菜单命令保存");
    }
}
public class Client {
    public static void main(String[] args) {
        Word word = new Word();
        OpenCommand o = new OpenCommand1();
        SaveCommand s = new SaveCommand2();
        word.setOpenCommand(o);
        word.setSaveCommand(s);
        word.open();
        word.save();
    }
}
/*
桌面双击文档的图标打开
ctrl+s保存
*/

请设计一个电子相册自动生成程序,要求该程序能够将一组图片自动生成到一个以树形结构保存的电子相册中,相册的目录采用树形结构,一级目录为年,二级目录为月,三级目录为日。每张照片可以添加音效和花边等特效。请写出你所选择的设计模式,画出类图,并给出核心代码

不透明组合模式 + 装饰模式

import java.util.ArrayList;

abstract class Album {
    protected String name;

    public Album() {
    }

    public Album(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void operation();
}
abstract class Dir extends Album {
    protected ArrayList<Album> list = new ArrayList<>();
    public Dir(String name) {
        super(name);
    }
    public void add(Album album) {
        list.add(album);
    }

    public void remove(Album album) {
        list.remove(album);
    }

    @Override
    public void operation() {
        for (Album album : list) {
            album.operation();
        }
    }
}
class Year extends Dir {

    public Year(String name) {
        super(name);
    }

    @Override
    public void operation() {
        System.out.println(name + "年");
        super.operation();
    }
}
class Month extends Dir {

    public Month(String name) {
        super(name);
    }

    @Override
    public void operation() {
        System.out.println(name + "月");
        super.operation();
    }
}
class Day extends Dir {

    public Day(String name) {
        super(name);
    }

    @Override
    public void operation() {
        System.out.println(name + "日");
        super.operation();
    }
}
class Picture extends Album {
    public Picture(String name) {
        super(name);
    }

    @Override
    public void operation() {
        System.out.println("图片:" + name);
    }

}
abstract class Decorator extends Album {
    protected Album pic;

    public Decorator() {
    }

    public void setPic(Album pic) {
        this.pic = pic;
    }

    @Override
    public void operation() {
        pic.operation();
    }
}
class Lace extends Decorator {

    @Override
    public void operation() {
        System.out.print("加花边");
        super.operation();
    }
}
class Sound extends Decorator {

    @Override
    public void operation() {
        System.out.print("加音效");
        super.operation();
    }
}
public class Client {
    public static void main(String[] args) {
        Picture cat, dog, monkey;
        Dir y2, m3, d4;
        cat = new Picture("小猫.jpg");
        dog = new Picture("小狗.jpg");
        monkey = new Picture("小猴.jpg");
        y2 = new Year("2022");
        m3 = new Month("3");
        d4 = new Day("4");
        d4.add(cat);
        d4.add(dog);
        d4.add(monkey);
        m3.add(d4);
        y2.add(m3);
        y2.operation();
        
        System.out.println("---------------------");
        System.out.println("给小猫加花边和音效得到:");
        Decorator lacecat = new Lace();
        lacecat.setPic(cat);
        Decorator lacesoundcat = new Sound();
        lacesoundcat.setPic(lacecat);
        lacesoundcat.operation();

        System.out.println("---------------------");
        d4.remove(cat);
        d4.add(lacesoundcat);
        y2.operation();
    }
}
/*
2022年
3月
4日
图片:小猫.jpg
图片:小狗.jpg
图片:小猴.jpg
---------------------
给小猫加花边和音效得到:
加音效加花边图片:小猫.jpg
---------------------
2022年
3月
4日
图片:小狗.jpg
图片:小猴.jpg
加音效加花边图片:小猫.jpg
*/

采用面向对象方法开发一个专营进口商品的电子商务系统,该系统有以下设计要求:

(1)需要根据不同的条件(如订单总额、商品数量、产品种类等),提供百分比折扣或现金减免等多种促销方式供提交订单的用户选择。实现每种促销活动的代码量很大,且会随促销策略不同经常修改。系统设计中需要考虑现有的促销和新的促销,而不用经常地重写控制器类代码;

(2)需要计算每个订单的税费,不同商品的税费及计算方式会有所区别。所以决定在系统中直接调用不同商品提供商提供的税费计算类,但每个供应商的类提供了不同的调用方法。系统设计中需要考虑如果商品更换了供应商,应该尽可能少地在系统中修改或创建新类。

请用恰当的设计模式来满足上述要求,画出类图,给出核心代码。

(1)策略模式:对订单提供策略,具体策略类都实现了抽象策略接口,客户端进行选择,可以增加新的策略,符合开闭原则。

(2)适配器模式:Tax 接口就是 Target ,对每个供应商都提供适配器,适配器都实现 Tax 接口,如果商品要改供应商,只需要重新注入一个 Tax 即可,符合开闭原则。

import java.util.ArrayList;

class Product {
    private String name;
    private double price;
    private Tax tax;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setTax(Tax tax) {
        this.tax = tax;
    }

    public double getPrice() {
        return price;
    }

    public double getTax() {
        return tax.getTax(price);
    }
}
interface Tax {
    public abstract double getTax(double price);
}
class Product1Adapter implements Tax{
    private Supplier1 supplier = new Supplier1();
    @Override
    public double getTax(double price) {
        return supplier.getTax1(price);
    }
}
class Product2Adapter implements Tax{
    private Supplier2 supplier = new Supplier2();
    @Override
    public double getTax(double price) {
        return supplier.getTax2(price);
    }
}
class Product3Adapter implements Tax{
    private Supplier3 supplier = new Supplier3();
    @Override
    public double getTax(double price) {
        return supplier.getTax3(price);
    }
}
class Supplier1 {
    public double getTax1(double price) {
        return price * 0.1;
    }
}
class Supplier2 {
    public double getTax2(double price) {
        return price * 0.2;
    }
}
class Supplier3 {
    public double getTax3(double price) {
        return price * 0.3;
    }
}
interface Strategy {
    public abstract double discount(double money);
}
class PercentStrategy implements Strategy {

    @Override
    public double discount(double money) {
        System.out.println("九折百分比折扣");
        return money * 0.9;
    }
}
class CashStrategy implements Strategy {

    @Override
    public double discount(double money) {
        System.out.println("50元现金折扣");
        return Math.max(money - 50 , 0);
    }
}
class Order {
    private double total;
    private double finaltotal;
    private double tax;
    private ArrayList<Product> list = new ArrayList<>();
    private Strategy strategy;

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public Order() {
    }
    public void addProduct(Product product) {
        list.add(product);
    }
    public double calTotal() {
        total = 0;
        for (Product product : list) {
            total += product.getPrice();
        }
        return total;
    }
    public double calTax() {
        tax = 0;
        for (Product product : list) {
            tax += product.getTax();
        }
        return tax;
    }
    public double calFinaltotal() {
        finaltotal = 0;
        calTotal();
        finaltotal = strategy.discount(total);
        return finaltotal;
    }

    public void getAllProducts() {
        for (Product product : list) {
            System.out.println(product.getName());
        }
    }
}
public class Client {
    public static void main(String[] args) {
        Product p1, p2, p3;
        Tax t1, t2, t3;
        Supplier1 supplier1 = new Supplier1();
        Supplier2 supplier2 = new Supplier2();
        Supplier3 supplier3 = new Supplier3();
        Order order;
        Strategy strategy;

        p1 = new Product("康师傅红烧牛肉面", 3.0);
        p2 = new Product("奥利奥", 6.5);
        p3 = new Product("猴头菇山药玉米糊", 6);
        t1 = new Product1Adapter();
        t2 = new Product2Adapter();
        t3 = new Product3Adapter();
        p1.setTax(t1);
        p2.setTax(t2);
        p3.setTax(t3);
        order = new Order();
        order.addProduct(p1);
        order.addProduct(p2);
        order.addProduct(p3);
        strategy = new PercentStrategy();
        order.setStrategy(strategy);

        System.out.println("-------------------------");
        System.out.println("订单中的所有商品:");
        order.getAllProducts();
        System.out.println("-------------------------");
        System.out.println("订单总金额(未促销):");
        System.out.println(order.calTotal());
        System.out.println("-------------------------");
        System.out.println("订单总税费:");
        System.out.println(order.calTax());
        System.out.println("-------------------------");
        System.out.println("订单总金额(促销):");
        System.out.printf("%.2f\n", order.calFinaltotal());
        System.out.println("-------------------------");
    }
}
/*
-------------------------
订单中的所有商品:
康师傅红烧牛肉面
奥利奥
猴头菇山药玉米糊
-------------------------
订单总金额(未促销):
15.5
-------------------------
订单总税费:
3.4
-------------------------
订单总金额(促销):
九折百分比折扣
13.95
-------------------------
*/ 

某公司想要开发一个智能家居系统,该系统中的家电自动控制子系统请你负责设计开发。该系统能够识别场景并给出恰当的响应,比如,该系统“看到”主人起床,就自动打开热水器、打开窗帘、启动扫地机器人等;“看到”主人出门,就自动关闭网络、启动防盗系统等;“看到”主人上床,就自动关闭窗帘、设置空调睡眠模式、关闭电视电脑等。请用恰当的设计模式实现这个子系统,画出类图,给出核心代码。

观察者模式

import java.util.HashMap;

interface Observer {
    public abstract void open();

    public abstract void shutdown();
}

class TV implements Observer {

    @Override
    public void open() {
        System.out.println("开启电视");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭电视");
    }
}

class Airconditioner implements Observer {

    @Override
    public void open() {
        System.out.println("开启空调");
    }

    @Override
    public void shutdown() {
        System.out.println("启动空调睡眠模式");
    }
}

class AntitheftSystem implements Observer {

    @Override
    public void open() {
        System.out.println("开启防盗系统");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭防盗系统");
    }
}

class Network implements Observer {

    @Override
    public void open() {
        System.out.println("打开网络");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭网络");
    }
}

class SweepRobot implements Observer {

    @Override
    public void open() {
        System.out.println("开启扫地机器人");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭扫地机器人");
    }
}

class Curtain implements Observer {

    @Override
    public void open() {
        System.out.println("开启窗帘");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭窗帘");
    }
}

class Computer implements Observer {

    @Override
    public void open() {
        System.out.println("开启电脑");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭电脑");
    }
}

class Heater implements Observer {

    @Override
    public void open() {
        System.out.println("开启热水器");
    }

    @Override
    public void shutdown() {
        System.out.println("关闭热水器");
    }
}

abstract class Subject {
    protected HashMap<String, Observer> observers = new HashMap<>();

    public void attach(String name, Observer observer) {
        observers.put(name, observer);
    }

    public void detach(String name) {
        observers.remove(name);
    }

    public abstract void getup();

    public abstract void goout();

    public abstract void gotobed();
}

class SmartSystem extends Subject {

    @Override
    public void getup() {
        observers.get("Heater").open();
        observers.get("Curtain").open();
        observers.get("SweepRobot").open();
    }

    @Override
    public void goout() {
        observers.get("Network").shutdown();
        observers.get("AntitheftSystem").open();
    }

    @Override
    public void gotobed() {
        observers.get("Curtain").shutdown();
        observers.get("Airconditioner").shutdown();
        observers.get("TV").shutdown();
        observers.get("Computer").shutdown();
    }
}

public class Client {
    public static void main(String[] args) {
        Subject system = new SmartSystem();
        Observer o1, o2, o3, o4, o5, o6, o7, o8;
        o1 = new TV();
        o2 = new Airconditioner();
        o3 = new AntitheftSystem();
        o4 = new Network();
        o5 = new SweepRobot();
        o6 = new Curtain();
        o7 = new Computer();
        o8 = new Heater();
        system.attach("TV", o1);
        system.attach("Airconditioner", o2);
        system.attach("AntitheftSystem", o3);
        system.attach("Network", o4);
        system.attach("SweepRobot", o5);
        system.attach("Curtain", o6);
        system.attach("Computer", o7);
        system.attach("Heater", o8);
        System.out.println("检测到主人起床:");
        system.getup();
        System.out.println("检测到主人出门:");
        system.goout();
        System.out.println("检测到主人上床:");
        system.gotobed();
    }
}
/*
检测到主人起床:
开启热水器
开启窗帘
开启扫地机器人
检测到主人出门:
关闭网络
开启防盗系统
检测到主人上床:
关闭窗帘
启动空调睡眠模式
关闭电视
关闭电脑
*/

设计一个“带名字的打印机”(说是打印机,其实只是将文字显示在界面上而已)。在Main类中会生成PrinterProxy类的实例(即“代理人”)。首先我们会给实例赋予名字Alice并在界面中显示该名字。接着会将实例名字改为Bob,然后显示该名字。在设置和获取名字时,都不会生成真正的Printer类的实例(即本人),而是由PrinterProxy类代理。最后,直到我们调用print方法,开始进入实际打印阶段后,PrinterProxy类才会生成Printer类的实例。给出设计模式的名称,画出类图,写出关键代码。

代理模式

interface Subject {
    public abstract void print(String name);
}
class Printer implements Subject {

    @Override
    public void print(String name) {
        System.out.println("显示名字:" + name);
    }
}
class PrinterProxy implements Subject {
    private Printer printer = new Printer();
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void print(String name) {
        printer.print(name);
    }
}
public class Client {
    public static void main(String[] args) {
        PrinterProxy printerProxy;
        printerProxy = new PrinterProxy();
        printerProxy.setName("Alice");
        printerProxy.print(printerProxy.getName());
        printerProxy.setName("Bob");
        printerProxy.print(printerProxy.getName());
    }
}
/*
显示名字:Alice
显示名字:Bob
*/

小王正在开发一套视频监控系统,考虑到 Windows Media Player 和 Real Player 是两种常用的媒体播放器,尽管它们的 API 结构和调用方法存在区别,但这套应用程序必须支持这两种播放器 API,而且在将来可能还需要支持新的媒体播放器。请你针对上面的描述,帮助小王进行设计,给出设计思路及所采用的设计模式,画出类图,并写出关键代码。

适配器模式

interface Target {
    public abstract void play();
}
class WindowsMediaPlayer {
    public void windowsPlay() {
        System.out.println("WindowsMediaPlayer 播放");
    }
}
class RealPlayer {
    public void realPlay() {
        System.out.println("RealPlayer 播放");
    }
}
class WindowsMediaPlayerAdapter implements Target {
    private WindowsMediaPlayer player = new WindowsMediaPlayer();
    @Override
    public void play() {
        player.windowsPlay();
    }
}
class RealPlayerAdapter implements Target {
    private RealPlayer player = new RealPlayer();
    @Override
    public void play() {
        player.realPlay();
    }
}
public class Client {
    public static void main(String[] args) {
        Target p1, p2;
        p1 = new WindowsMediaPlayerAdapter();
        p2 = new RealPlayerAdapter();
        p1.play();
        p2.play();
    }
}
/*
WindowsMediaPlayer 播放
RealPlayer 播放
*/

银行信用卡中心的电子账单系统包括了发送器、账单、广告信和发送队列等对象,其中广告信的业务逻辑是:先到数据库中把客户信息一个一个的取出,每个客户都生成一份个性化的邮件,然后交给发送机进行发送处理。请问哪种设计模式设计广告信较好?请画出UML设计类图

原型模式

软件公司要开发一个图形界面组件库,界面租借分为两大类,一类是单元控件,例如按钮、文本框等,一类是容器控件,例如对话框、表单等,请问采用何种模式设计比较好?请画出UML设计类图。

组合模式

化妆品公司的报表系统可将不同月份的销售数据以柱状图、曲线图和饼状图等多种形式展示出来,各个月份的销售数据可以从文本文件中获取,也可以从数据库中获取,还可以从Excel文件中获取。如果需要从Excel文件中获取数据,则需要调用与Excel相关的API,而这个API是现有系统所不具备的,该API有厂商提供。请问采用何种设计模式设计比较好?请画出UML设计类图。

桥接模式和适配器模式

标签: 画出 万元 请你