OOP/OOD练习建议与相关模板(基础类封装模板,必须掌握) 【from 黄老师】

针对Java OOP题目中高频核心场景的通用代码模板(Starter Code),覆盖基础封装、对象排序、继承多态、接口实现、综合系统建模五大核心场景,可根据具体题目需求微调,所有模板均符合Java OOP最佳实践(封装、高内聚低耦合)。


📌 Core OOP Java 知识点覆盖

这些题目重点练习以下 Java OOP 核心概念:

  • 封装 Encapsulation:类设计、隐藏内部细节
  • 继承 Inheritance:父类与子类关系、extends
  • 多态 Polymorphism:父类/接口引用指向子类对象
  • 接口 Interface:自定义接口 + implements
  • 抽象 Abstract:抽象类 + 抽象方法设计
  • Comparable/Comparator:排序与比较机制实现

1. 基础类封装模板(适配入门级题目:P5740/P5741/P5742/P1001等)

适用场景

定义实体类(如学生、苹果、金币等),封装属性和行为,实现基础的对象创建、属性访问、业务逻辑计算。

import java.util.Scanner;

// 以P5740【最厉害的学生】为例:封装Student类
public class Main {
    // 1. 实体类:私有属性 + 构造方法 + getter/setter + 业务方法
    static class Student {
        // 私有属性(封装核心:隐藏内部状态)
        private String name;
        private int chinese;
        private int math;
        private int english;
        
        // 构造方法:初始化对象
        public Student(String name, int chinese, int math, int english) {
            this.name = name;
            this.chinese = chinese;
            this.math = math;
            this.english = english;
        }
        
        // 业务方法:封装计算逻辑(高内聚)
        public int getTotalScore() {
            return chinese + math + english;
        }
        
        // Getter方法:对外提供属性访问(可控)
        public String getName() {
            return name;
        }
        
        // 可选:重写toString,方便调试输出
        @Override
        public String toString() {
            return name + " " + chinese + " " + math + " " + english + " 总分:" + getTotalScore();
        }
    }

    // 主方法:程序入口,处理输入输出 + 调用对象方法
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine(); // 吸收换行符
        
        Student topStudent = null;
        int maxScore = 0;
        
        // 创建多个对象并遍历
        for (int i = 0; i < n; i++) {
            String[] info = sc.nextLine().split(" ");
            String name = info[0];
            int chinese = Integer.parseInt(info[1]);
            int math = Integer.parseInt(info[2]);
            int english = Integer.parseInt(info[3]);
            
            Student s = new Student(name, chinese, math, english);
            int total = s.getTotalScore();
            
            // 对象比较逻辑
            if (total > maxScore) {
                maxScore = total;
                topStudent = s;
            }
        }
        
        // 输出结果
        System.out.println(topStudent);
        sc.close();
    }
}

2. Comparable/Comparator 排序模板(适配普及级题目:P1068/P1093/P1104/P1567等)

适用场景

需要对自定义对象进行排序(单/多关键字排序),如奖学金排名、考生分数线划定、生日排序等。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

// 以P1093【奖学金】为例:多关键字排序
public class Main {
    // 1. 定义实体类(实现Comparable接口:自然排序)
    static class Student implements Comparable<Student> {
        private int id; // 学号
        private int chinese;
        private int math;
        private int english;
        private int total;

        public Student(int id, int chinese, int math, int english) {
            this.id = id;
            this.chinese = chinese;
            this.math = math;
            this.english = english;
            this.total = chinese + math + english;
        }

        // 核心:重写compareTo,定义排序规则
        // 规则:总分降序 → 语文降序 → 学号升序
        @Override
        public int compareTo(Student o) {
            if (this.total != o.total) {
                return o.total - this.total; // 降序:用o - this
            }
            if (this.chinese != o.chinese) {
                return o.chinese - this.chinese;
            }
            return this.id - o.id; // 升序:this - o
        }

        // Getter + toString
        public int getId() {
            return id;
        }

        @Override
        public String toString() {
            return id + " " + total;
        }
    }

    // 2. 可选:Comparator接口(自定义排序,灵活度更高)
    static class StudentComparator implements Comparator<Student> {
        @Override
        public int compare(Student s1, Student s2) {
            // 可定义与自然排序不同的规则
            return s1.getId() - s2.getId();
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        ArrayList<Student> list = new ArrayList<>();
        
        // 初始化对象列表
        for (int i = 0; i < n; i++) {
            int id = i + 1; // 假设学号从1开始
            int chinese = sc.nextInt();
            int math = sc.nextInt();
            int english = sc.nextInt();
            list.add(new Student(id, chinese, math, english));
        }
        
        // 排序方式1:使用Comparable自然排序
        Collections.sort(list);
        
        // 排序方式2:使用Comparator自定义排序(按需选择)
        // Collections.sort(list, new StudentComparator());
        
        // 输出结果
        for (Student s : list) {
            System.out.println(s);
        }
        sc.close();
    }
}

3. 继承与多态模板(适配提高级题目:P1551/P1957/P2482等)

适用场景

需要抽象公共属性/行为,通过继承复用代码,通过多态实现不同子类的差异化行为(如猪国杀的角色、口算练习题的运算类型)。

import java.util.Scanner;

// 以P2482【猪国杀】简化版为例:角色继承 + 多态
public class Main {
    // 1. 父类:抽象公共属性和行为
    static abstract class Role {
        protected String name; // 角色名
        protected int hp; // 血量

        public Role(String name, int hp) {
            this.name = name;
            this.hp = hp;
        }

        // 抽象方法:子类必须实现(多态核心)
        public abstract void skill(Role target);

        // 通用方法:所有子类复用
        public void hurt(int damage) {
            this.hp -= damage;
            System.out.println(name + "受到" + damage + "点伤害,剩余血量:" + hp);
        }

        // Getter
        public String getName() {
            return name;
        }

        public int getHp() {
            return hp;
        }
    }

    // 2. 子类1:主公(重写抽象方法)
    static class Lord extends Role {
        public Lord() {
            super("主公", 10); // 调用父类构造
        }

        @Override
        public void skill(Role target) {
            System.out.println(name + "对" + target.getName() + "使用主公技能,造成2点伤害");
            target.hurt(2);
        }
    }

    // 3. 子类2:反贼(重写抽象方法)
    static class Rebel extends Role {
        public Rebel() {
            super("反贼", 8);
        }

        @Override
        public void skill(Role target) {
            System.out.println(name + "对" + target.getName() + "使用反贼技能,造成1点伤害");
            target.hurt(1);
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        // 多态:父类引用指向子类对象
        Role lord = new Lord();
        Role rebel = new Rebel();
        
        // 调用子类的skill方法(运行时多态)
        lord.skill(rebel);
        rebel.skill(lord);
        
        sc.close();
    }
}

4. 接口实现模板(适配提高级题目:P2089/P3367/P3370等)

适用场景

需要定义行为规范,让不同类实现同一接口(如烤鸡的配方计算、并查集的操作、字符串哈希策略)。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 以P2089【烤鸡】为例:接口定义配方计算规则
public class Main {
    // 1. 定义接口:规范行为
    interface RecipeCalculator {
        // 计算n克调料的所有配方组合
        List<List<Integer>> calculate(int n);
    }

    // 2. 实现接口:具体的配方计算逻辑
    static class ChickenRecipe implements RecipeCalculator {
        private static final int MAX_PER_SPOON = 3; // 每勺最多3克
        private List<List<Integer>> result;

        @Override
        public List<List<Integer>> calculate(int n) {
            result = new ArrayList<>();
            backtrack(n, new ArrayList<>(), 0);
            return result;
        }

        // 回溯算法(封装在实现类内部,对外隐藏细节)
        private void backtrack(int remain, List<Integer> path, int count) {
            if (count == 10) { // 固定10勺
                if (remain == 0) {
                    result.add(new ArrayList<>(path));
                }
                return;
            }
            for (int i = 1; i <= MAX_PER_SPOON; i++) {
                if (i > remain) break;
                path.add(i);
                backtrack(remain - i, path, count + 1);
                path.remove(path.size() - 1);
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); // 总克数
        
        // 面向接口编程:依赖接口而非具体实现
        RecipeCalculator calculator = new ChickenRecipe();
        List<List<Integer>> recipes = calculator.calculate(n);
        
        // 输出结果
        System.out.println(recipes.size());
        for (List<Integer> recipe : recipes) {
            for (int num : recipe) {
                System.out.print(num + " ");
            }
            System.out.println();
        }
        sc.close();
    }
}

5. 综合系统建模模板(适配省选级题目:P1563/P2482/P2586等)

适用场景

复杂系统模拟(如玩具谜题、杀蚂蚁、猪国杀),需拆分多个类协作,封装状态和行为,降低耦合。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 以P1563【玩具谜题】为例:多类协作建模
public class Main {
    // 1. 玩具人类:封装状态和行为
    static class Toy {
        private String job; // 职业
        private int direction; // 朝向:0=内,1=外

        public Toy(String job, int direction) {
            this.job = job;
            this.direction = direction;
        }

        // 根据朝向和步数计算下一个位置
        public int getNextIndex(int currentIdx, int step, int total) {
            if (direction == 0) { // 朝内:左数(索引减)
                return (currentIdx - step + total) % total;
            } else { // 朝外:右数(索引加)
                return (currentIdx + step) % total;
            }
        }

        public String getJob() {
            return job;
        }
    }

    // 2. 游戏类:封装游戏逻辑(高内聚)
    static class ToyPuzzleGame {
        private List<Toy> toys;
        private int currentIdx; // 当前选中的玩具索引

        public ToyPuzzleGame(List<Toy> toys) {
            this.toys = toys;
            this.currentIdx = 0; // 初始位置
        }

        // 执行一次操作
        public void executeOperation(int step) {
            Toy currentToy = toys.get(currentIdx);
            currentIdx = currentToy.getNextIndex(currentIdx, step, toys.size());
        }

        // 获取当前结果
        public String getCurrentJob() {
            return toys.get(currentIdx).getJob();
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); // 玩具数量
        int m = sc.nextInt(); // 操作次数
        
        // 初始化玩具列表
        List<Toy> toys = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            int dir = sc.nextInt();
            String job = sc.next();
            toys.add(new Toy(job, dir));
        }
        
        // 创建游戏对象,执行操作
        ToyPuzzleGame game = new ToyPuzzleGame(toys);
        for (int i = 0; i < m; i++) {
            int dir = sc.nextInt();
            int step = sc.nextInt();
            game.executeOperation(step);
        }
        
        // 输出结果
        System.out.println(game.getCurrentJob());
        sc.close();
    }
}

总结

  1. 模板核心原则:所有模板均遵循「封装(私有属性+公共方法)、高内聚(业务逻辑封装在类内部)、低耦合(类间通过接口/方法调用交互)」,符合Java OOP最佳实践。
  2. 使用技巧
    • 入门题优先用「基础类封装模板」,聚焦属性和方法封装;
    • 排序题优先用「Comparable/Comparator模板」,注意多关键字排序的规则定义;
    • 提高/省选题根据场景选择「继承多态」或「接口实现」模板,复杂系统用「综合建模模板」拆分类。
  3. 通用调整点:根据具体题目修改实体类的属性、业务方法的逻辑、排序规则或接口实现细节,主方法的输入输出逻辑可复用模板结构。
posted @ 2026-02-13 08:45  kkman2000  阅读(8)  评论(0)    收藏  举报