zoukankan      html  css  js  c++  java
  • 设计模式第一次作业

    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);
    
  • 相关阅读:
    Oracle的导入导出
    Android利用数据库传送数据
    Android相对布局实例
    git拉取github项目
    kafka支持认证SASL_PLAINTEXT
    fluentd插件开发
    解决go依赖包安装问题
    ES/Kibana支持search-guard认证
    logkit docker运行和代码下载
    CentOS安装指定git版本
  • 原文地址:https://www.cnblogs.com/htd6/p/7768623.html
Copyright © 2011-2022 走看看