设计模式第一次作业
github地址
1、要求:某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等;用户可以根据要求动态选择日志记录方式。使用Factory模式来设计;如果系统中增加一个日志记录方式—控制台日志记录(ConsoleLog),类图将如何改变?
github地址
类图:
系统中增加一个日志记录方式—控制台日志记录(ConsoleLog):
源码:
//日志接口
public interface Log {
void write();
}
//日志工厂接口
public interface LogFactory {
Log produceLog();
}
//数据库日志
public class DatabaseLog implements Log {
@Override
public void write() {
System.out.print("write log to database");
}
}
//数据库日志工厂
public class DatabaseLogFactory implements LogFactory{
@Override
public Log produceLog() {
return new DatabaseLog();
}
}
//文件日志
public class FileLog implements Log {
@Override
public void write() {
System.out.print("write log to file");
}
}
//文件日志工厂
public class FileLogFactory implements LogFactory{
@Override
public Log produceLog() {
return new FileLog();
}
}
//测试代码
public class LogTest {
private final String PROPERTY_KEY = "log.factory.class";
@Test
public void test() throws Exception{
//从配置文件中获取工厂类型
LogFactory logFactory = (LogFactory) TestUtil.getClassFromProperties(PROPERTY_KEY).newInstance();
//从日志工厂中得到日志并操作
logFactory.produceLog().write();
}
}
2、要求:某系统为了改进数据库操作的性能,自定义数据连接对象Connection和语句对象Statement,可针对不同类型的数据库提供不同的连接对象和语句对象;用户可以通过配置文件等方式根据实际需要动态更换系统数据库;使用Abstract Factory模式来设计。
github地址
类图:
源码:
//连接接口
public interface Connection {
void connect();
}
//语句接口
public interface Statement {
void execute();
}
//数据库操作工厂接口
public interface DatabaseFactory {
Connection produceConnection();
Statement produceStatement();
}
//mysql连接
public class MysqlConnection implements Connection {
@Override
public void connect() {
System.out.println("Mysql connect success");
}
}
//mysql语句操作
public class MysqlStatement implements Statement{
@Override
public void execute() {
System.out.println("Mysql statement execute success");
}
}
//mysql数据库操作工厂
public class MysqlDatabaseFactory implements DatabaseFactory {
@Override
public Connection produceConnection() {
return new MysqlConnection();
}
@Override
public Statement produceStatement() {
return new MysqlStatement();
}
}
//oracle连接
public class OracleConnection implements Connection {
@Override
public void connect() {
System.out.println("Oracle connect success");
}
}
//oracle语句
public class OracleStatement implements Statement{
@Override
public void execute() {
System.out.println("Oracle statement execute success");
}
}
//oracle数据库操作工厂
public class OracleDatabaseFactory implements DatabaseFactory {
@Override
public Connection produceConnection() {
return new OracleConnection();
}
@Override
public Statement produceStatement() {
return new OracleStatement();
}
}
//数据库操作测试
public class DatabaseTest {
private final String PROPERTY_KEY = "database.factory.class";
@Test
public void test() throws Exception{
//从配置文件中加载工厂类别
DatabaseFactory databaseFactory = (DatabaseFactory) TestUtil.getClassFromProperties(PROPERTY_KEY).newInstance();
//数据库连接
databaseFactory.produceConnection().connect();
//语句执行
databaseFactory.produceStatement().execute();
}
}
3、要求:KFC套餐是一个复杂对象,一般包括主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)组成部分,不同套餐有不同组成部分;KFC服务员要根据顾客要求,装配这些组成部分,构造一个完整套餐,返回给顾客;使用Builder模式来设计。
github地址
类图:
源码:
//套餐
public class Meal {
private String food;
private String drink;
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
//套餐创建者
public abstract class MealBuilder {
private Meal meal = new Meal();
abstract void buildFood();
abstract void buildDrink();
public Meal getMeal(){
return meal;
}
}
//KFC服务员
public class KFCWaiter {
private MealBuilder mealBuilder;
public void setMealBuilder(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public Meal constructMeal(){
mealBuilder.buildFood();
mealBuilder.buildDrink();
return mealBuilder.getMeal();
}
}
//套餐A创建者
public class MealABuilder extends MealBuilder{
@Override
void buildFood() {
getMeal().setFood("Hamburger");
}
@Override
void buildDrink() {
getMeal().setDrink("fruit juice");
}
}
//套餐B创建者
public class MealBBuilder extends MealBuilder{
@Override
void buildFood() {
getMeal().setFood("fried chicken");
}
@Override
void buildDrink() {
getMeal().setDrink("cola");
}
}
//KFC测试
public class KFCTest {
private final String PROPERTY_KEY = "kfc.builder.class";
@Test
public void test() throws Exception{
KFCWaiter kfcWaiter = new KFCWaiter();
//从配置文件加载套餐创建者
MealBuilder mealBuilder = (MealBuilder) TestUtil.getClassFromProperties(PROPERTY_KEY).newInstance();
//设置套餐创建者
kfcWaiter.setMealBuilder(mealBuilder);
//创建套餐
Meal meal = kfcWaiter.constructMeal();
//显示结果
System.out.printf(" the meal contains food %s and drink %s\n", meal.getFood(), meal.getDrink());
}
}
4、要求:游戏中的地图:包括天空、地面、背景;人物包括人体、服装、装备等组成部分,如采用Builder模式如何设计?
github地址
类图:
源码:
//地图
public class Map {
private String sky;
private String ground;
private String background;
public String getSky() {
return sky;
}
public void setSky(String sky) {
this.sky = sky;
}
public String getGround() {
return ground;
}
public void setGround(String ground) {
this.ground = ground;
}
public String getBackground() {
return background;
}
public void setBackground(String background) {
this.background = background;
}
}
//地图创建者
public abstract class MapBuilder {
private Map map = new Map();
abstract void buildSky();
abstract void buildGround();
abstract void buildBackground();
public Map getMap() {
return map;
}
}
//角色
public class Role {
private String body;
private String colthing;
private String equip;
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getColthing() {
return colthing;
}
public void setColthing(String colthing) {
this.colthing = colthing;
}
public String getEquip() {
return equip;
}
public void setEquip(String equip) {
this.equip = equip;
}
}
//角色创建者
public abstract class RoleBuilder {
private Role role= new Role();
abstract void buildBody();
abstract void buildClothing();
abstract void buildEquip();
public Role getRole() {
return role;
}
}
//游戏
public class Game {
private MapBuilder mapBuilder;
private RoleBuilder roleBuilder;
public void setMapBuilder(MapBuilder mapBuilder) {
this.mapBuilder = mapBuilder;
}
public void setRoleBuilder(RoleBuilder roleBuilder) {
this.roleBuilder = roleBuilder;
}
public Map constructMap(){
mapBuilder.buildSky();
mapBuilder.buildGround();
mapBuilder.buildBackground();
return mapBuilder.getMap();
}
public Role constructRole(){
roleBuilder.buildBody();
roleBuilder.buildClothing();
roleBuilder.buildEquip();
return roleBuilder.getRole();
}
}
//地图A创建者
public class MapABuilder extends MapBuilder {
@Override
void buildSky() {
getMap().setSky("blue");
}
@Override
void buildGround() {
getMap().setGround("smooth");
}
@Override
void buildBackground() {
getMap().setBackground("nothing");
}
}
*/
//地图B创建者
public class MapBBuilder extends MapBuilder {
@Override
void buildSky() {
getMap().setSky("black");
}
@Override
void buildGround() {
getMap().setGround("rough");
}
@Override
void buildBackground() {
getMap().setBackground("dirty");
}
}
//角色A创建者
public class RoleABuilder extends RoleBuilder {
@Override
void buildBody() {
getRole().setBody("strong");
}
@Override
void buildClothing() {
getRole().setColthing("sports wear");
}
@Override
void buildEquip() {
getRole().setEquip("sword");
}
}
//角色A创建者
public class RoleABuilder extends RoleBuilder {
@Override
void buildBody() {
getRole().setBody("strong");
}
@Override
void buildClothing() {
getRole().setColthing("sports wear");
}
@Override
void buildEquip() {
getRole().setEquip("sword");
}
}
//游戏测试
public class GameTest {
private final String MAP_PROPERTY_KEY = "game.mapBuilder.class";
private final String ROLE_PROPERTY_KEY = "game.roleBuilder.class";
@Test
public void test() throws Exception{
//从配置文件加载地图创建者
MapBuilder mapBuilder = (MapBuilder) TestUtil.getClassFromProperties(MAP_PROPERTY_KEY).newInstance();
//从配置文件加载角色创建者
RoleBuilder roleBuilder = (RoleBuilder) TestUtil.getClassFromProperties(ROLE_PROPERTY_KEY).newInstance();
//设置游戏的创建者
Game game = new Game();
game.setMapBuilder(mapBuilder);
game.setRoleBuilder(roleBuilder);
//创建地图和角色
Map map = game.constructMap();
Role role = game.constructRole();
//显示结果
System.out.printf("the map sky %s ground %s background %s\n", map.getSky(), map.getGround(), map.getBackground());
System.out.printf("the role body %s clothing %s equip %s\n", role.getBody(), role.getColthing(), role.getEquip());
}
}
5、某系统需要提供一个加密模块,将用户信息(如密码等)加密之后再存储在数据库中,系统已经定义好数据库操作类。为了提高开发效率,现要重用已有的加密算法,这些算法由第三方提供,没有源码。如采用Adapter模式如何设计?
github地址
类图:
源码:
//加密类
public class Encryptor {
public void encrypt(){
System.out.println("info encrypt success");
}
}
//数据库操作类
public class DatabaseOperator {
public void saveInfo(){
System.out.println("save info to database success");
}
}
//加密的数据库操作适配器类
public class DatabaseEncryptOperator extends DatabaseOperator {
private Encryptor encryptor;
public DatabaseEncryptOperator(Encryptor encryptor){
this.encryptor = encryptor;
}
@Override
public void saveInfo() {
encryptor.encrypt();
super.saveInfo();
}
}
public class EncryptTest {
@Test
public void test(){
//数据库操作类指定为加密的数据库操作适配类
DatabaseOperator databaseOperator = new DatabaseEncryptOperator(new Encryptor());
//数据库操作
databaseOperator.saveInfo();
}
}