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

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



题目六

请为上海中心大厦设计一个大楼管理系统。大厦由地上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);
    }
}

猜你喜欢

转载自blog.csdn.net/KQwangxi/article/details/121860538