设计模式第一次作业
设计模式第一次作业
1、要求:某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等;用户可以根据要求动态选择日志记录方式。使用Factory模式来设计;如果系统中增加一个日志记录方式—控制台日志记录(ConsoleLog),类图将如何改变?
类图如下:
代码:
abstract class factory{//工厂的抽象类
public abstract Log recordLogs();
}
class TextLogFactory extends factory{//文字日志工厂类
public Log recordLogs() {
// TODO Auto-generated method stub
return new TextLog();
}
}
class DBLogFactory extends factory{//数据库日志工厂类
public Log recordLogs() {
// TODO Auto-generated method stub
return new DBLog();
}
}
abstract class Log{//日志生成器抽象类
public abstract void WriteLogs();
}
class TextLog extends Log{//文字日志生成器
public void WriteLogs() {
// TODO Auto-generated method stub
System.out.println("textLog");
}
}
class DBLog extends Log{//数据库日志生成器
public void WriteLogs() {
// TODO Auto-generated method stub
System.out.println("dbLog");
}
}
//测试代码
factory fa=new DBLogFactory();
Log log = fa.recordLogs();
log.WriteLogs();
如果此时加入ConsoleLog,类图变为如下:
2、要求:某系统为了改进数据库操作的性能,自定义数据连接对象Connection和语句对象Statement,可针对不同类型的数据库提供不同的连接对象和语句对象;用户可以通过配置文件等方式根据实际需要动态更换系统数据库;使用Abstract Factory模式来设计。
类图如下:
代码:
abstract class Factory{//工厂抽象类
public abstract Statement setStatement();
public abstract Connection setConnection();
}
class AccessFactory extends Factory{//access数据库的工厂
public Statement setStatement() {
// TODO Auto-generated method stub
return new AccessStatement();
}
public Connection setConnection() {
// TODO Auto-generated method stub
return new AccessConnection();
}
}
class SqlFactory extends Factory{//sql server数据库的工厂
public Statement setStatement() {
// TODO Auto-generated method stub
return new SqlStatement();
}
public Connection setConnection() {
// TODO Auto-generated method stub
return new SqlConnection();
}
}
class Statement{
}
class AccessStatement extends Statement{//access数据库的statement
public AccessStatement() {//在这里假定在构造时即产生了statement
System.out.println("AccessStatement");
}
}
class SqlStatement extends Statement{//sql server数据库的statement
public SqlStatement() {//在这里假定在构造时已产生了statement
System.out.println("SqlStatement");
}
}
class Connection{
}
class AccessConnection extends Connection{//access数据库的connection
public AccessConnection() {//在这里假定在构造时已产生了connection
System.out.println("AccessConnection");
}
}
class SqlConnection extends Connection{//sql server数据库的connection
public SqlConnection() {
System.out.println("SqlConnection");
}
}
//测试代码
Factory fa=new SqlFactory();
fa.setConnection();
fa.setStatement();
小结
从这两题看出:
- 使用工厂模式的情况下,数据与操作并未完全分离,如第一题的文字日志生成器与数据库日志生成器,他们虽然进行着不同的操作,但是他们的数据可以说是同一份或者说是来自同一个地方。
- 工厂模式,形象的说,就是一个人面前有很多店,但是,一个店只能买到一个物品。比如,在米店只能买到米,在面店只能买到面。所以,在第一题中对应的是,在TextFactory中,返回TextLog对象,在DBLogFactory ,返回DBLog对象。
- 使用抽象工厂模式的情况下,各个工厂的操作等均是完全分离的。如第二题的AccessFactory与SqlFactory,他们连接数据库所使用的statement与connection是完全不同的。
- 抽象工厂模式,形象的说,就是一个人面前有很多超市,每个超市都可以大于一个的东西。比如AccessFactory里可以有AccessStatement和AccessConnection,在SqlFactory中可以有SqlStatement和SqlConnection。
3、要求:KFC套餐是一个复杂对象,一般包括主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)组成部分,不同套餐有不同组成部分;KFC服务员要根据顾客要求,装配这些组成部分,构造一个完整套餐,返回给顾客;使用Builder模式来设计。
类图如下:
代码:
abstract class FoodBuilder{//套餐builder 系统中真正的builder
FoodGetted foodGetted;
public FoodBuilder() {
foodGetted=new FoodGetted();
}
public abstract void bulidFood();
public abstract void bulidDrink();
public FoodGetted getFood(){
return foodGetted;
}
}
class PackageAFoodBuilder extends FoodBuilder{//套餐A的builder
public void bulidFood() {//套餐A的主食
// TODO Auto-generated method stub
foodGetted.setFood(" PackageA food-汉堡");
}
public void bulidDrink() {//套餐A的饮料
// TODO Auto-generated method stub
foodGetted.setDrink(" PackageA drink-可乐");
}
}
class PackageBFoodBuilder extends FoodBuilder{//套餐B的builder
public void bulidFood() {//套餐B的主食
// TODO Auto-generated method stub
foodGetted.setFood(" PackageA food-鸡肉卷");
}
public void bulidDrink() {//套餐B的饮料
// TODO Auto-generated method stub
foodGetted.setDrink(" PackageA drink-果汁");
}
}
class Waiter{//服务员去调用建造命令
private FoodBuilder foodBuilder;
public void setFoodBuilder(FoodBuilder foodBuilder) {
this.foodBuilder=foodBuilder;
}
public FoodGetted buildOrderedFood() {
// TODO Auto-generated method stub
foodBuilder.bulidFood();
foodBuilder.bulidDrink();
return foodBuilder.getFood();
}
}
class Customer{//系统的点餐者 一定程度上也就充当了director 告知waiter该做什么
private Waiter waiter;
public void orderFoodA(Waiter w){
waiter=w;
waiter.setFoodBuilder(new PackageAFoodBuilder());
}
public void orderFoodB(Waiter w){
waiter=w;
waiter.setFoodBuilder(new PackageBFoodBuilder());
}
public void customerGetted(FoodGetted foodGetted){
System.out.println("customerGetted is "+foodGetted.getFood()+" "+foodGetted.getDrink());
}
}
class FoodGetted{//通过调用最终得到的食物
private String drink;
private String food;
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
}
//测试代码
//消费者进入 店内已有waiter 消费者点A套餐并告知waiter waiter去build点的餐 之后获取消费者得到的餐
Customer c=new Customer();
Waiter waiter = new Waiter();
c.orderFoodA(waiter);
c.customerGetted(waiter.buildOrderedFood());
4、要求:游戏中的地图:包括天空、地面、背景;人物包括人体、服装、装备等组成部分,如采用Builder模式如何设计?
类图如下:
如果看不清,请点这里
代码:
class Map{ //对应的是最终生成的map的product
private String Sky;
private String Ground;
private String Background;
public String getSky() {
return Sky;
}
public void setSky(String sky) {
Sky = sky;
}
public String getGround() {
return Ground;
}
public void setGround(String ground) {
Ground = ground;
}
public String getBackground() {
return Background;
}
public void setBackground(String background) {
Background = background;
}
}
abstract class MapBuilder{//map的builder 三个抽象方法 要求子类实现地图最基本的三个元素
//包括天空、地面、背景
Map map;
public MapBuilder() {
map=new Map();
}
public abstract void buildSky();
public abstract void buildGround();
public abstract void buildBackground();
public Map getMap(){
return map;
}
}
class NormalMapBuilder extends MapBuilder{//正常map的builder 写三个具体的build方法来完成map的三个元素
public void buildSky() {
// TODO Auto-generated method stub
map.setSky("NormalMapBuilder Sky");
}
public void buildGround() {
// TODO Auto-generated method stub
map.setGround("NormalMapBuilder Ground");
}
public void buildBackground() {
// TODO Auto-generated method stub
map.setBackground("NormalMapBuilder Background");
}
}
class AbnormalMapBuilder extends MapBuilder{//非正常map的builder 写三个具体的build方法来完成map的三个元素
public void buildSky() {
// TODO Auto-generated method stub
map.setSky("AbnormalMapBuilder Sky");
}
public void buildGround() {
// TODO Auto-generated method stub
map.setGround("AbnormalMapBuilder Ground");
}
public void buildBackground() {
// TODO Auto-generated method stub
map.setBackground("AbnormalMapBuilder Background");
}
}
class People{//对听的是最终的people的product
private String Body;
private String Clothes;
private String Equipments;
public String getBody() {
return Body;
}
public void setBody(String body) {
Body = body;
}
public String getClothes() {
return Clothes;
}
public void setClothes(String clothes) {
Clothes = clothes;
}
public String getEquipments() {
return Equipments;
}
public void setEquipments(String equipments) {
Equipments = equipments;
}
abstract class PeopleBuilder{//三个抽象方法 对应人物的三个基本元素
//人物包括人体、服装、装备等组成部分
People people;
public PeopleBuilder() {
people=new People();
}
public abstract void buildBody();
public abstract void buildClothes();
public abstract void buildEquipments();
public People getPeople(){
return people;
}
}
class LowLevelPeopleBuilder extends PeopleBuilder{//低等级的人物 具体实现三个方法
public void buildBody() {
// TODO Auto-generated method stub
people.setBody("LowLevelPeopleBuilder Body");
}
public void buildClothes() {
// TODO Auto-generated method stub
people.setClothes("LowLevelPeopleBuilder Clothes");
}
public void buildEquipments() {
// TODO Auto-generated method stub
people.setEquipments("LowLevelPeopleBuilder Eduipments");
}
}
class HighLevelPeopleBuilder extends PeopleBuilder{//高等级的人物 具体实现的三个方法
public void buildBody() {
// TODO Auto-generated method stub
people.setBody("HighLevelPeopleBuilder Body");
}
public void buildClothes() {
// TODO Auto-generated method stub
people.setClothes("HighLevelPeopleBuilder Clothes");
}
public void buildEquipments() {
// TODO Auto-generated method stub
people.setEquipments("HighLevelPeopleBuilder Eduipments");
}
}
class Creator{ //建造者 调用真正的建造者
private MapBuilder mm;
private PeopleBuilder peopleBuilder;
public Creator(MapBuilder m,PeopleBuilder p) {
mm=m;
peopleBuilder=p;
}
public Map creatMapBuilder() {
mm.buildSky();
mm.buildGround();
mm.buildBackground();
return mm.getMap();
}
public People creatPeopleBuilder() {
peopleBuilder.buildBody();
peopleBuilder.buildClothes();
peopleBuilder.buildEquipments();
return peopleBuilder.getPeople();
}
public void GameGetted(Map map,People people){//使用creator生成的类来测验得到的game地图
System.out.println("The sky in game is "+map.getSky()+
",the ground in game is "+map.getGround()+
",the background in game is "+map.getBackground());
System.out.println("The body in game is "+people.getBody()+
",the clothes in game is "+people.getClothes()+
",the equipments in game is "+people.getEquipments());
}
}
//测试代码
//前两行充当一个director的角色
MapBuilder m=new NormalMapBuilder();
PeopleBuilder p=new HighLevelPeopleBuilder();
//得到传过来的map与people
Creator creator=new Creator(m,p);
//进行构造 并将构造好的map与people的信息进行返回
creator.GameGetted(creator.creatMapBuilder(), creator.creatPeopleBuilder());
小结
从这两题看出:
- 建造者模式,如同名字,就是去建造,需要的时候才构建,如第四题的creator,在需要的时候才会调用creatMap()与creatPeople(),creator只管调用,而真实的构建是在对应的MapBuilder与PeopleBuilder中。
- 也就是,户主(client)要建房子,将要建房子的类型(三角顶,白瓷砖外墙)(对应代码的map、people)告诉包工头(Creator),包工头(Creator)吩咐手里的几个工程队(MapBuilder ,PeopleBuilder )去建造,所以,真正的实施,是由工程队完成。
5、某系统需要提供一个加密模块,将用户信息(如密码等)加密之后再存储在数据库中,系统已经定义好数据库操作类。为了提高开发效率,现要重用已有的加密算法,这些算法由第三方提供,没有源码。如采用Adapter模式如何设计?
类图如下:
代码:
class DBoperator {//已知的数据库操作类
public String password;
Adapter ad;
public void setAdapter(){//在这个类中,一定会有设置adapter的方法
//构造一个adapter类继承自原来的adapter
ad=new EncryptAdapter();
//将密码传过去进行加密即可
password=ad.encryptPassword(password);
}
}
abstract class Adapter {
public abstract String encryptPassword(String password);
}
class EncryptAdapter extends Adapter{//再新增的adapter中调用第三方算法
ThirdMethod method;
public String encryptPassword(String password) {
// TODO Auto-generated method stub
method=new ThirdMethod();
return method.doEncrypt(password);
}
}
class ThirdMethod{//adaptee
//这里由于不知道具体加密算法的源码 假定方法体是这样 主要是便于测试
public String doEncrypt(String pwd){
System.out.println("第三方加密pwd");
return pwd+"123213";
}
}
//测试代码
DBoperator dbo=new DBoperator();
dbo.password="23";
dbo.setAdapter();
System.out.println(dbo.password);
小结
- 适配器模式,就是将原本已存在的方法通过适配器来匹配当前的需求。比如将电脑充电器将电网中的220V标准电压转换成为电脑电池的充电电压。在本题中,已经有数据库操作类和第三方加密算法类,但是,他们无法通讯啊,就如同有电脑和墙壁插座,所以呢,需要一个适配器。将密码传给适配器,让适配器去调用第三方加密算法给出的方法进行操作,再将操作结果返回即可。