设计模式第一次作业
2017-11-02 23:23
316 查看
1.题目1
要求:某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等;用户可以根据要求动态选择日志记录方式。使用Factory模式来设计;如果系统中增加一个日志记录方式—控制台日志记录(ConsoleLog),类图将如何改变?解答
根据工厂模式设计以下类图:实现代码如下:
// 抽象日志工厂类 public abstract class LogFactory { abstract Log createLog(); }
// 文本日志工厂类 public class TextLogFactory extends LogFactory { @Override Log createLog() { return new TextLog(); } }
// 数据库日志工厂类 public class DBLogFactory extends LogFactory { @Override Log createLog() { return new DBLog(); } }
// 抽象日志产品类 public abstract class Log { abstract void add(); abstract void delete(); abstract void query(); }
// 文本日志产品类 public class TextLog extends Log { @Override void add() { System.out.println("add a text log"); } @Override void delete() { System.out.println("delete a text log"); } @Override void query() { System.out.println("query a text log"); } }
用户调用代码如下:
LogFactory factory = new TextLogFactory(); // 根据用户要求动态选择Factory具体类 Log log = factory.createLog(); log.add();
如果系统中增加一个日志记录方式—控制台日志记录,类图改变如下:
2.题目2
要求:某系统为了改进数据库操作的性能,自定义数据连接对象Connection和语句对象Statement,可针对不同类型的数据库提供不同的连接对象和语句对象;用户可以通过配置文件等方式根据实际需要动态更换系统数据库;使用Abstract Factory模式来设计。解答
类图如下:代码实现如下:
// 数据库抽象工厂类 public abstract class DBFactory { public abstract Connection makeConnection(); public abstract Statement makeStatement(); }
// 数据库连接抽象产品类 public abstract class Connection { public abstract void connect(); }
// 数据库语句抽象产品类 public abstract class Statement { public abstract void query(); }
// MySql数据库连接 public class MySqlConnection extends Connection { @Override public void connect() { System.out.println("connect to mysql"); } }
// MySql数据库语句 public class MySqlStatement extends Statement { @Override public void query() { System.out.println("make a mysql query"); } }
// MySql数据库工厂类 public class MySqlDBFactory extends DBFactory { @Override public Connection makeConnection() { return new MySqlConnection(); } @Override public Statement makeStatement() { return new MySqlStatement(); } }
用户调用如下:
DBFactory factory = new MySqlDBFactory(); // 可以根据配置文件更换为具体的数据库工厂类 Connection connection = factory.makeConnection(); Statement statement = factory.makeStatement(); connection.connect(); statement.query();
3.题目3
要求:KFC套餐是一个复杂对象,一般包括主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)组成部分,不同套餐有不同组成部分;KFC服务员要根据顾客要求,装配这些组成部分,构造一个完整套餐,返回给顾客;使用Builder模式来设计。解答
类图如下:代码如下:
// 套餐创建者抽象类 public abstract class ComboBuilder { protected Combo combo; public ComboBuilder() { this.combo = new Combo(); } public Combo getCombo() { return combo; } public abstract void buildStaple(); public abstract void buildDrink(); }
// 套餐导演抽象类 public abstract class ComboDirector { protected ComboBuilder builder; public ComboDirector(ComboBuilder builder) { this.builder = builder; } public abstract Combo construct(); }
// 套餐导演具体类,同时创建主食和饮料 public class ComboDoubleDirector extends ComboDirector { public ComboDoubleDirector(ComboBuilder builder) { super(builder); } @Override public Combo construct() { builder.buildStaple(); builder.buildDrink(); return builder.getCombo(); } }
// 套餐创建者具体类,创建各个part(即主食和饮料) public class FamilyComboBuilder extends ComboBuilder { @Override public void buildStaple() { combo.add("Hamburger"); } @Override public void buildDrink() { combo.add("Coke"); } }
// 套餐产品类 public class Combo { private ArrayList<String> foods = new ArrayList<>(); public void add(String food) { foods.add(food); } public void show(){ for (String food : foods) { System.out.println(food); } } }
用户调用如下:
ComboBuilder builder = new FamilyComboBuilder(); // 指定具体的创建者类 ComboDirector director = new ComboDoubleDirector(builder); // 指定具体的组合规则类 Combo combo = director.construct();; // 导演类按照类定义的规则组合各个part combo.show();
4.题目4
要求:游戏中的地图:包括天空、地面、背景;人物包括人体、服装、装备等组成部分,如采用Builder模式如何设计?解答
类图如下:代码如下:
// 地图创建者抽象类 public abstract class MapBuilder { protected Map map; public MapBuilder() { this.map = new Map(); } public Map getMap() { return map; } public abstract void buildSky(); public abstract void buildGround(); public abstract void buildBackground(); }
// 沙漠地图创建者具体类 public class DesertMapBuilder extends MapBuilder { @Override public void buildSky() { map.setSky("gray"); } @Override public void buildGround() { map.setGround("sand"); } @Override public void buildBackground() { map.setBackground("yellow"); } }
// 地图导演类 public class MapDirector { private MapBuilder builder; public MapDirector(MapBuilder builder) { this.builder = builder; } public Map construct() { builder.buildSky(); builder.buildGround(); builder.buildBackground(); return builder.getMap(); } }
用户调用如下:
MapBuilder builder = new DesertMapBuilder(); // 指定具体的创建者类 MapDirector director = new MapDirector(builder); // 指定具体的组合规则类 Map map = director.construct(); map.show();
Factory模式和Builder模式的对比
从创建出来的产品进行分析,Factory最终创建单一产品,而观察Builder可以发现,其最终也只产生一个产品,但是该产品比较复杂,是一个复合产品,由多个零件构成。如第4题,如果使用Factory模式,单个Factory只能单一产生天空、地面或背景,而一个Builder能分别创建三个零件,创建后零件的组合规则是在Director类中定义,Builder最终产生一个完整的Map。所以,当一个产品构成比较复杂,可能复合了多个零件,但用户不想了解每个零件的生成过程,他最终只想要一个完整的产品,那么就应该采用Builder模式。而当用户最终需要的产品比较简单,可以将该产品看成是Builder模式下的一个part,这时就应该使用Factory模式了,因为用户就很有可能会更换这个产品的实现。5.题目5
要求:某系统需要提供一个加密模块,将用户信息(如密码等)加密之后再存储在数据库中,系统已经定义好数据库操作类。为了提高开发效率,现要重用已有的加密算法,这些算法由第三方提供,没有源码。如采用Adapter模式如何设计?解答
类图如下:代码如下:
// Target public abstract class Encryption { public abstract String encrypt(String str); }
// Adapter public class EncryptionAdapter extends Encryption { private ThirdPartyEncryption adaptee; public EncryptionAdapter(ThirdPartyEncryption adaptee) { this.adaptee = adaptee; } @Override public String encrypt(String str) { return adaptee.encrypt(str); } }
用户调用如下:
Encryption encryption = new EncryptionAdapter(adaptee); encryption.encrypt(str);