设计模式第一次作业

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地址

类图:

kfc

源码:

//套餐
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();
    }
}