吉林大学设计模式第二次作业

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


题目一

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

答案:

请添加图片描述
这道题我选择的是抽象工厂模式,也就是根据产品种类,客户端需求去判断生成对应的类。
我把衣服相关的都放在一个clothes中去实现,学校的实现分为一中、二中和三中,看了上面的uml相信我也不用多说什么了,这道题比较简单,我感觉自己对面对对象编程有点感觉了,不过自己看了看写的代码,挺多地方都不规范,下次注意。

public class Clothes {
	public void fallShirt() {
		System.out.print("+ 秋季长袖");
	}
	public void fallTrousers() {
		System.out.print("+ 秋季长裤");
	}
	public void summerShorts() {
		System.out.print("+ 夏季短裤子");
	}
	public void summerShortSleevedShirt() {
		System.out.print("+ 夏季短袖衬衣");
	}
	public void summerTrousers() {
		System.out.print("+ 夏季长裤");
	}
	public void summerTShirt() {
		System.out.print("+ 夏季短袖T恤");
	}
}

class School {
    public void showSchool() {}
}

class School1 extends School{
	public void showSchool() {
		System.out.println("一中:");
	}
}

class School2 extends School{
	public void showSchool() {
		System.out.println("二中:");
	}
}

class School3 extends School{
	public void showSchool() {
		System.out.println("三中:");
	}
}

package homework2;

class Season {
    public Clothes clothes;
    public void getClothes() {	   
    }
}

class Autumn extends Season{
	public Clothes clothes;
	public Autumn() {
		clothes = new Clothes(); 
	}
	public void getClothes() {	 
		clothes.fallShirt();
		clothes.fallTrousers();
    }
}

class Summer extends Season{
	public Clothes clothes;
	public Summer() {
		clothes = new Clothes(); 
	}
	public void getClothes() {
		clothes.summerTShirt();
		clothes.summerShortSleevedShirt();
		clothes.summerTrousers();
		clothes.summerShorts();
	}
}


import java.util.Scanner;

public class Uniform {
    
	public static void main(String[] args) {
		 
		 Scanner sc = new Scanner(System.in);
         System.out.println("请输入当前需求:");
         String in = sc.nextLine();
         //“+”需要转义
         String[] split = in.split("\\+");
//         System.out.println(split[0]);
//         System.out.print(split[1]);
         if(split[0].equals("一中")) {
        	 School1 s1 = new School1();
        	 s1.showSchool();
         }else if(split[0].equals("二中")) {
        	 School2 s2 = new School2();
        	 s2.showSchool();
         }else if(split[0].equals("三中")) {
        	 School3 s3 = new School3();
        	 s3.showSchool();
         }
         
         
         if(split[1].equals("夏季")) {
        	 Summer season = new Summer();
        	
        	 season.getClothes();
         }
         if (split[1].equals("秋季")) {
        	 Autumn season = new Autumn();
        	 season.getClothes();      	 
         }
	}

}


输出是这样的:

请添加图片描述
请添加图片描述


题目二

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

分析这道题,它其实自己也说了,尽管文件格式不同,但都分为了三个部分,并按照一定的步骤呈现。所以我觉得这道题可以使用建造者模式,其相关的定义为:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。

其实感觉这里和上面那道题的抽象工厂模式有点像,不过再抽象一下的话,建造者模式和工厂模式的关注点不同——建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程。
建造者模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成,在这道题里面(括号里是我抄的相关定义帮助自己理解):

  • 产品:就是文件的三个部分(它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。)
  • 抽象建造者:我写了一个接口类interface Builder,里面的三个方法控制文件三个部分的生成(它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 )
  • 具体建造者:我定义了一个 Operate类,并且其中的方法控制了文件的一些实现细节,比如这道题里说的逗号分隔和换行 (实现Builder 接口,完成复杂产品的各个部件的具体创建方法)
  • 指挥者:也就是我们的Client端了,(它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息)

请添加图片描述

public class File {
	protected String file_type="text";
	public String get_type(){
		return file_type;
	}
	public int set_type(String settype) {
		file_type = settype;
		return 0;
	}
	///文件头开始:
	public void number() {
		System.out.print("分公司或门市点编号");
	}
	public void date() {
		System.out.print("导出数据的日期");
	}
	/*public void file_head() {
		System.out.println("分公司或门市点编号、导出数据的日期");
		//这样写在一起无法应对文本格式添加逗号的要求
	}*/
	///文件头结束
	
	///文件体开始
	public void table_name() {
		System.out.print("表名称");
	}
	public void describe() {
		System.out.print("分条描述数据");
	}
	/*
	public void file_body() {
		System.out.println("表名称、然后分条描述数据");
	}*/
	///文件体结束
	
	///文件尾开始
	public void file_tail() {
		System.out.println("输出人:");
	}
	///文件尾结束


}

public interface Builder {
	public void head() ;
	public void body() ;
	public void tail() ;
}

public class Operate extends File implements Builder {
	public void head() {
		System.out.print("输出文件头");
		super.number();
		if(get_type().equals("text")) {
			System.out.print(",");
		}
		super.date();
	}
	public void body() {
		System.out.print("输出文件体");
		//super.file_body();
		super.table_name();
		if(get_type().equals("text")) {
			System.out.println(" ");//另起一行
		}
		super.describe();
		if(get_type().equals("text")) {
			System.out.print(",");
		}
	}
	public void tail() {
		System.out.print("输出文件尾");
		super.file_tail();
	}
}

public class Client {
	public static void main(String[] args) {
		//System.out.println("hello word");
		// 首先创建出一个输出文件的机器人->robot
		Builder robot=new Operate();
		robot.head();
		robot.body();
		robot.tail();
	}
}

题目三

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

在这里插入图片描述

这道题非常简单,按照要求使用的是单例模式(保证一个类仅有一个实例,并提供一个访问它的全局访问点)

public class TicketMaker {
	//创建 SingleObject 的一个对象
	   private static TicketMaker countTicket;
	   private static int ticket =1000;
	   //让构造函数为 private,这样该类就不会被实例化
	   private TicketMaker(){}
	 
	   //获取唯一可用的对象
	   public static TicketMaker getNextTicketNumber(){
		  if(countTicket == null) {
			  countTicket = new TicketMaker();
		  }
		  ticket+=1;
	      return countTicket;
	   }
	 
	   public void showMessage(){
	      System.out.println(countTicket.ticket);
	   }
	      
	public static void main(String[] args) {

	      //获取唯一可用的对象
		for(int i = 0; i<10 ; i++) {
		  TicketMaker object = TicketMaker.getNextTicketNumber();
		  object.showMessage();
		}
	}
}

这是输出:
请添加图片描述


题目四

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

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;
}

哈哈哈这是大鸟小菜书上的一个情景欸!
首先分析源代码哪里有问题(问题大大的!):

  • 除法判别里如果numb为0,这种错误没有处理
  • 之前讲到过业务逻辑一定要分装实现接口隔离原则和单一职责原则,在这段简单的代码里,计算功能和显示功能杂糅到了一起,这很不好(但这道题好像没要求输出设备,所以这里的改进就暂且先不考虑输出单独包装)
  • 这个计算器太逊了,如果日后要新增开根号等运算,需要不断增加case改动现有代码,所以最好每个运算有个公共的父类,并使用简单工厂模式,在实际解决时去实例化相应的运算类对象。

使用的模式是简单工厂模式,根据需求实例化相应的运算类。

#include <iostream>
#include<string>
using namespace std;
 
//运算类的父类 
class Calculate{
public:
    Calculate(){};
    int result;
    int alu(){return result;}
};

//实现加法运算 
class add : public Calculate
{
public:
    add(int x,int y){result=x+y;}
};

//实现减法运算 
class sub:public Calculate
{
public:
    sub(int x,int y){result=x-y;}
};

//实现乘法运算 
class mul:public Calculate{
public:
    mul(int x,int y){result=x*y;}
};

//实现除法运算 
class chu:public Calculate{
public:
    chu(int x,int y){
    	int b=y;
    	if(b==0){
            	cout<<"除数为0,请重新输入!"<<endl;
            	cin>>b;
			}
	    result=x/b;
	}
};

//采用简单工厂模式,根据需求实例化对应的运算类 
class Calculate_Factory
{
public:
    Calculate_Factory(){};
    Calculate* produce(char method,int a,int b){
        if(method=='+'){
            cout<<"运算方法:加法"<<endl;
            return new add(a,b);
        }
        else if(method=='-')
        {
            cout<<"运算方法:减法"<<endl;
            return new sub(a,b);
        }
        else if(method=='*')
        {
            cout<<"运算方法:乘法"<<endl;
            return new mul(a,b);
        }else if(method=='/')
        {
            cout<<"运算方法:除法"<<endl;   
            return new chu(a,b);
        }
        else
            cout<<"无法识别运算方法"<<endl;
    }
};
int main()
{
    int numa,numb;
    char oper;
    double result;
    cin>>numa>>numb;
    cin>>oper;
    Calculate_Factory* factory = new Calculate_Factory();
    result=factory->produce(oper,numa,numb)->alu();
    cout<<result<<endl;
    return 0;
}

题目五

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

class DBConnections {

public:

   DBConnections ( ) { ... } 

   ~ DBConnections ( ) { ... }

   void ConnectionInfo ( ) { ... }

 };

答案分析:

单例模式,构造方法私有化,同时注意使用static静态方法和参数:

package homework2_5;

public class DBConnections {
	private static DBConnections temp=null;
	private static int count=0;
	private DBConnections(){}
	public static DBConnections ConnectionInfo () {
		if(count<3) {
			temp = new DBConnections();
		    count++;
		    System.out.println("这是第 "+count+"个对象" );
		}
		if(count>=3)
			System.out.println("该类不可再实例化!" );
		return temp;
	}

	public static void main(String[] args) {
		DBConnections object = null;
		// TODO Auto-generated method stub
		for(int i=0;i<10;i++)
			object = DBConnections.ConnectionInfo();
	}
}

输出:

请添加图片描述

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作业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功能。
吉林大学软件学院设计模式是该学院在软件工程专业中教授的一门课程。在该课程中,学生将学习使用分类稳定和变化的方法来重新设计类,以便使得新设计能够以扩展代码的方式适应未来的变化。学生还将根据给出的类图,设计并实现相关类,并修改原程序,以确保输出结果不变。此外,课程还包括其他方面的作业,如实现美观的输出结果和使用访问者模式设计和实现玩家行为等。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [吉林大学软件学院卓班设计模式第一次作业](https://download.csdn.net/download/sjzdwk/11892325)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [吉林大学软件学院卓班设计模式第三次练习](https://download.csdn.net/download/sjzdwk/11892684)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [吉林大学软件学院卓班设计模式第四次练习](https://download.csdn.net/download/sjzdwk/11892642)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值