吉林大学设计模式第四次作业(下)

找到这里的多半是我的学弟学妹了,怎么说呢,希望能帮到你们吧,也更希望我留在这里的思路和代码是你们的下限,设计模式真的很精妙,祝你们有所增益。



题目六

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

老师给的标准答案:开放题!嘻嘻嘻嘻,可以使用组合模式、迭代器模式、工厂模式、原型模式等
采用的设计模式是组合模式
请添加图片描述

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.print("room distrbute:"+room+"pipeline:"+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("叶子节点没有子节点");

}

}

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)

{

(region)list.get(i);

} 

}

public class client

{

public static void main(String []args)

{

region happyroom = new buildingInfo("娱乐房间","垂直管线");

region happybuilding = new mainbuilding("娱乐",35);

happybuilding.Add(happyroom);

happybuilding.display();

}

}


题目七

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

1)简要说明你的设计思路和选择的模式。
通过原文中:公司的经纪每租出一个物业,主管就会收到相应的租赁信息,所以我选择观察者模式。
2)给出你设计的UML类图和实现代码。
请添加图片描述

import java.util.ArrayList;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			TV tv;
			TVFactory factory;
			factory = (TVFactory)XMLUtil.getBean();
			tv=factory.produceTV();
			tv.play();
		}
		catch(Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

abstract class House{
	public String id =null;
	public double price;
	public int status;
	protected ArrayList<StakeHolder> stakeholders = new ArrayList <StakeHolder>();
	public void setStatus(int status) {
		this.status = status;
		for(Object obj:stakeholders) {
			(Stakeholder)obj.response(this);
		}
	}
	public void addStakeholder(StakeHolder sh) {
		stakeholder.add(sh);
		System.out.println("添加一个业主。");
	}
}

//具体房屋类
class Villadom extends House{
	public Villadom() {
		System.out.println("这是一个房屋类A");
	}
}

//具体房屋类
class Apartment extends House{
	public Apartment() {
		System.out.println("这是一个房屋类B");
	}
}

//房屋工厂
abstract class HouseCreater{
	public House createHouse() {
		return null;
	}
}

//具体房屋工厂
class VilladomCreater{
	public House createHouse() {
		System.out.println("VilladomCreater");
		return new Villadom();
	}
}


//具体房屋工厂
class ApartmentCreater{
	public House createHouse() {
		System.out.println("Apartment");
		return new Apartment();
	}
}

//观察者模式部分
interface StakeHolder{
	//声名响应方法
	public void response(House house);
}

class Manager implement StakeHolder{
	//实现响应方法
	public void response(House house) {
		System.out.println("收到租赁信息,并记录!");
	}
}


题目八

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

老师给的标准答案(可以有两种思路):
①把抽象策略的接口改成抽象类,然后在里面实现具体算法的公共功能;
②给所有具体策略算法定义一个抽象的父类,让这个父类去实现策略的接口,然后在这个父类里面去实现公共的功能
更推荐第二种,因为这样可以在父类这个抽象类里定义算法实现的骨架,然后让具体的策略算法去实现变化的部分,上述的结构实际就是模板方法。抽象类就是模板方法模式的模板类。

答案来源
代码需要复用,且算法实现步骤相同,考虑加入模板模式,在超类里实现复用部分(公共功能及实现步骤),在子类里实现局部不同的部分

public abstract class Strategy {
	private void com_method1() {
		System.out.println("这里是可复用步骤1");
	}
	private void com_method2() {
		System.out.println("这里是可复用步骤2");
	}
	protected abstract void method3();
	protected void methon() {
		com_method1();
		com_method2();
		method3();
	}
}

题目九

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

这道题hhhh我又写错了,很明显的题干:当温度T;所以要用状态模式,别看了别看了,太瓜了,职责链属于强行指鹿为马了

我选择职责链模式。

请添加图片描述

package homework4_9;

class System{
	int temperature;
	int T;
	System s = null;
	protected System() {
		
	}
	public void getTem(int x) {
		if (s == null) {
			s = new System();
		}
		this.temperature=x;
		s.change();
	}
	public void setNext(System next) {

        this.s = next;

    }
	public System getNext() {

        return s;

    }
	public void change() {
		
	}
}

class LowTem extends System{
    public void change() {
    	if (s.temperature< T) {
    		//升高温度
    	}
    	else {
    		s.getNext().change();
    	}		
	}
}

class UpTem extends System{
    public void change() {
    	if (s.temperature>T) {
    		//降低温度
    	}
    	else {
    		s.getNext().change();
    	}		
	}
}
public class Client {

	public static void main(String[] args) {
		 //组装责任链

		System s1= new  LowTem();
		System s2 = new UpTem();
        s1.setNext(s2);

        
	}

}

题目十

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

(老师给的标准答案是:策略模式)老师这么解释的:
①半价和积分都是会员卡活动,用装饰模式进行叠加的话把颗粒度画的太细了,它们属于同一个策略比较合理;
②当然必要时这个策略可以进行扩展。

对于这道题里的票价计算,计算方式会经常发生变动,在运行期间,不同人员参与的计算方式也是不同的,这就意味着需要在运行期间动态来组合需要计算的部分,也就是会有一堆的if-else;甚至会有新的需求,这就要求我们的设计实现要足够灵活,要能够很快进行相应调整和修改。所以感觉这道题可以使用装饰模式,不同的计价规则之间可以叠加。

  • Component:组件对象的接口,可以给这些对象动态的添加职责。(这道题里面我们可以在这个接口里面定义计算票价的业务方法,因为外部就是使用这个接口来操作装饰模式构成的对象结构中的对象)
  • ConcreteComponent:具体的组件对象,实现组件对象接口,通常就是被装饰器装饰的原始对象,也就是可以给这个对象添加职责。(对标本题就是添加一个基本的实现组件接口的对象,比如让它返回原票价,反正可以重写)
  • Decorator:所有装饰器的抽象父类,需要定义一个与组件接口一致的接口,并持有一个Component对象,其实就是持有一个被装饰的对象(注意这个被装饰的对象不一定是最原始的那个对象了,也可能是被其它装饰器装饰过后的对象,反正都是实现的同一个接口,也就是同一类型)
  • ConcreteDecorator:实际的装饰器对象,实现具体要向被装饰对象添加的功能。(把各个计算票价的规则实现成为具体的装饰器对象)

请添加图片描述

//计算票价的组件接口
public abstract class Component {
    /**
     * 计算票价哦,有些参数在演示中并不会使用,
     * 但是在实际业务实现上是会用的,为了表示这是个具体的业务方法,
     * 因此这些参数被保留了
     * @param user 人数
     * @param begin 开票的时间
     */
    public abstract double calcPrize(String user,Date begin);
}
//业务接口提供一个基本的实现ConcreteComponent类
public class ConcreteComponent extends Component{
    public double calcPrize(String user, Date begin, Date end) {
       //只是一个默认的实现,默认票价没有折扣
       return 0;
    }
}
//定义抽象的装饰器:定义所有装饰器对象需要实现的方法
public abstract class Decorator extends Component{
    //持有被装饰的组件对象
    protected Component c;
    /*通过构造方法传入被装饰的对象
     * @param c被装饰的对象
     */
    public Decorator(Component c){
       this.c = c;
    }
    public double calcPrize(String user, Date begin, Date end) {
       //转调组件对象的方法
       return c.calcPrize(user, begin);
    }
}

//定义一系列具体的装饰器对象,每一个都可以实现一种计算票价的规则,现在有三条计算奖金的规则,那就对应有三个装饰器对象来实现,依次来看看它们的实现。
//装饰器对象①:学生凭学生证可享受票价7折优惠

public class StudentPrizeDecorator extends Decorator{
    public StudentPrizeDecorator(Component c){
       super(c);

    }  

    public double calcPrize(String user, Date begin, Date end) {
       //1:先获取前面运算出来的票价
       double money = super.calcPrize(user, begin);
       //2:然后按照学生政策给予优惠
       double prize = TempDB.mapMonthSaleMoney.get(user) * 0.7;
       System.out.println(user+"当月业务奖金"+prize);
       return prize;
    }
}

//装饰器对象②:年龄在10周岁及以下的儿童可享受每张票减免15元的优惠(原始票价需大于等于30元)
public class ChildPrizeDecorator extends Decorator{
    public ChildPrizeDecorator(Component c){
       super(c);
    }  
    public double calcPrize(String user, Date begin, Date end) {
       //1:先获取前面运算出来的票价
       double money = super.calcPrize(user, begin);
       //2: 年龄在10周岁及以下的儿童可享受每张票减免15元的优惠(原始票价需大于等于30元)
       double prize = money;
       if(money >= 30)
           prize = money - 15;
       System.out.println(user+"累计奖金"+prize);
       return money + prize;
    }
}

//装饰器对象③:影院会员卡用户除享受票价半价优惠外还可进行积分,积分累计到一定额度可换取电影院赠送的奖品。
public class SumPrizeDecorator extends Decorator{
    public SumPrizeDecorator(Component c){
       super(c);
    }
    public double calcPrize(String user, Date begin) {
       //1:先获取前面运算出来的票价
       double money = super.calcPrize(user, begin, end);
       //2:然后积分
       //3:按需要进行奖品兑换操作
    }
}
/*使用装饰器的客户端*/
public class Client {
    public static void main(String[] args) {
       //先创建计算基本奖金的类,这也是被装饰的对象
       Component c1 = new ConcreteComponent();
       /*然后对计算的票价进行装饰,这里要组合各个装饰
        *说明,各个装饰者之间最好是不要有先后顺序的限制,
        *也就是先装饰谁和后装饰谁都应该是一样的*/
       //先学生优惠
       Decorator d1 = new StudentPrizeDecorator(c1);
       Decorator d2 = new ChildPrizeDecorator(d1);
       //注意:这里只需使用最后组合好的对象调用业务方法即可,会依次调用回去
       //日期对象都没有用上,所以传null就可以了
       double zs = d2.calcPrize("张三",null);      
       System.out.println("==========张三应付钱:"+zs);
       double ls = d2.calcPrize("李四",null);
       System.out.println("==========李四应付钱:"+ls);
       //如果进行积分
       Decorator d3 = new SumPrizeDecorator(d2);
       double ww = d3.calcPrize("王五",null);
    }
}
作业02 字符图像 目标:开发字符图像的类。一个字符图像是由多行ANSI可打印字符组成的,各行字符数量可以不同;一个字符图像可以通过加框(Frame)形成一个的字符图像;两个字符图像可以通过顶端对齐的方式经水平连接(HCat)形成一个的字符图像;两个字符图像可以通过左端对齐的方式经垂直连接(VCat)形成一个的字符图像; 1. 现给出了一个字符图像的类定义,如下 实现上边的CharPic类。 2. 上边CharPic中,通过重载构造函数创建字符图像,但构造函数的语义不是非常直观,使用也需要特别小心。请试一试将重载的构造函数改成(简单)工厂方法,使得语义更清晰。 3. 考察完成的代码,你发现: a) 在构造、拷贝、赋值时,将各子图都重构造了一遍,拷贝和赋值使用的也是深拷贝和深赋值,这样在合成复杂的字符图像过程中,子图需要频繁地复制或赋值,效率不高; b) 在使用一个字符图像对象的过程中,不改变字符图像中的字符,因此重构建子图、深复制、深拷贝显得没有必要; c) 合成一个的字符图像后,图像不含有关于”合成过程”的信息,即图像不知道是通过水平连接得到的,还是垂直连接得到的,也不知道“左子图”是什么等。 为此,重设计了CharPic(为方便对比,类名改为Pic),希望通过子类型化和共享来避免abc中的问题。类的结构图(部分)如下: 其中,由于子类型化的存在,字符图像的拷贝采用了原型方法模式 (即虚拟拷贝构造函数);同时,禁止了图像对象间的赋值。 请定义并实现上述类图中的相关类,以及用于示例的相应主程序。 4. 若已知在复用3中的类时,可能增加有一些其它的需求,如: a) 增加对角线连接的字符图像 b) 显示时,可通过指定图像间隔(空白字符个数)显示字符图像; c) 变更FamePic中外框的字符(如变更为$号) d) 增加以加密的形式显示字符图像功能,如将字符图像中的A显示成Z,Z显示成Y。 e) 增加图像的swap功能,即交换左右或上下(对于SimplePic和FramePic的Swap,不做操作即可) 请继续对3中的类,使用桥接模式重设计,部分类图如下;同时指出如何适应a-e的变化需求. 5. 现有Menu类及相关类,如下图 在显示AppleMenu和WindowMenu时,是以图片的形式显示的;对于ConsoleMenu当然也以图片形式显示更一致些,但若完全实现该功能,可能比较繁琐,可以考虑复用已有的字符图像类。为此,请分别以类适配器模式和对象适配器模式,复用字符图像类,实现ConsoleMenu的show功能。
作业03 结构型模式 1. 现Mouse类的定义如下: class Mouse { public: void Walk( int steps ) { cout<<"Implement for Walk() with Verson 1."} void AddMoney(int m) { cout<<"Implement for AddMoney() with Verson 1."} private: int posX; int posY; }; 若已知:在后续的版本中 a)可能增加Mouse类的其他行为,如增加Drive(int steps)和Fly(int steps); b)可能需要改变Walk(int steps)的具体实现细节; c)可能增加其它数据成员,如将2D位置信息改为3D位置信息等。 d)希望在版本中,尽可能地通过扩展老版本,适应需求。 请使用桥接模式重设计Mouse类及相关类,并简要说明如何适应变化a-d。 2. 请设计并实现一个foo.dll,其中含有类如下: a) 若foo.dll直接导出了类Foo、类FooA、类FooB,请使用类适配器和对象适配器,实现 class User { public: int myProcess( ) { /*适配Foo.process(); */ } }; b) 若foo.dll没有导出类Foo、类FooA、类FooB,但导出函数shared_ptr createFooA();和shared_ptr createFooB();,请使用对象适配器使得User可以适配任意指定的Foo类族的子类对象的process。 3. 针对给出的场景、描述,请说出最适当的模式名字,并用文字或示例代码给出简要的使用说明或解释。 1) 开发了一个用于数值计算的大型程序库,它的功能是强大的,但需要使用者具备较高的数学专业知识。为方便“菜鸟”级用户的使用,需要提供一个简化版的,但同时又不希望影响专业人员的使用。使用哪种设计模式较好?如何设计? 2) 在2D游戏的开发中,需要绘制地图,地图是由大量的“一样的图块”拼接而成,而“图块”的种类有限,目前有草地、海洋、沙漠、山地等,未来肯定要增加种类,但不太多太频繁。采用何种模式组织“图块”类比较好?如何设计? 3) 在开发一个办公自动化系统时,项目组在ElectricSignature类集中实现了电子签名的功能。但在使用中发现该类不能完全满足用户需求,由于财力和人员的限制,决定直接购买第三方电子签名软件,其中的FZ_ESignet类功能与ElectricSignature的功能一样,但是两个类中的函数名都是不一样的,而且购买的只是二进制代码,没有源代码。现希望使用第三方软件的功能,但又不希望修改ElectricSignature的接口。使用哪种设计模式改进较好?如何改进? 4) 某书店需要开发一套图书购销存软件。在设计图书类时发现:图书有单行本和成套的,又细分成教辅材料、科学知识、文学著作等。设计时,希望能够以一致的方式访问各种图书,不论是单本的、成套的、IT类的或古典名著。使用哪种设计模式较好?如
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值