【连载】Java学习系列(008)——深入面向对象-2
来源:互联网 发布:java web中启动线程池 编辑:程序博客网 时间:2024/06/05 22:42
【连载】Java学习系列(008)——深入面向对象-2
- 接口:在Java中,接口是实现可插入特性的保证。定义接口的关键字是interface,实现接口的关键字是implements,一个类可以实现多个接口,接口之间的继承支持多重继承。
接口和抽象类的异同
- 相同点:都不能被直接实例化,都可以通过继承实现其抽象方法。
- 不同点:
1,抽象类里可以有构造方法,而接口内不能有构造方法。
2,抽象类中可以有普通成员变量,而接口中不能有普通成员变量。
3,抽象类中可以包含非抽象的普通方法,而接口中所有的方法必须是抽象的,不能有非抽象的普通方法。
4,抽象类中的抽象方法的访问类型可以是public ,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5,抽象类中可以包含静态方法,接口内不能包含静态方法。
6,抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static类型,并且默认为public static类型。
7,一个类可以实现多个接口,但只能继承一个抽象类。
都是面向抽象编程的技术基础,实现了诸多的设计模式。
类/类和类/接口之间的关系
- IS-A关系:继承/实现
- HAS-A关系:关联/聚合(聚集)/合成
- USE-A关系:依赖
- UML:统一建模语言(标准的图形化符号)
- 类图:描述类以及类和类之间关系的图形符号。
- 用例图:捕获需求。
- 时序图:描述对象交互关系。
- 面向对象的设计原则
- 单一职责原则(SRP):类的设计要做到高内聚,一个类只承担单一的职责(不做不该它做的事情)。
- 开闭原则(OCP):软件系统应该接受扩展(对扩展开放),不接受修改(对修改关闭)。要符合开闭原则:抽象是关键,封装可变性。
- 依赖倒转原则(DIP):面向接口编程。声明变量的引用类型,声明方法的参数类型,声明方法的返回类型时,尽可能使用抽象类型而不是具体类型。
- 里氏替换原则(LSP):用子类型替换父类型没有任何问题,用父类型替换子类型通常都是不行的。
- 接口隔离原则(ISP):接口要小而专,不能大而全。
- 合成聚合复用原则(CARP):优先考虑用强关联关系复用代码,而不是用继承关系复用代码。
- 迪米特法则(LoD):对象之间尽可能少的发生联系。
练习:五子棋
package com.lovoinfo;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import javax.swing.ImageIcon;import javax.swing.JDialog;@SuppressWarnings("serial")public class RenjuDialog extends JDialog { private RenjuPanel panel = new RenjuPanel(); public RenjuDialog() { this.setTitle("五子棋"); this.setSize(625, 645); this.setResizable(false); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); this.setIconImage(new ImageIcon("renju.png").getImage()); this.add(panel); this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_F2) { panel.reset(); repaint(); } } }); } public static void main(String[] args) { new RenjuDialog().setVisible(true); }}
package com.lovoinfo;import java.awt.Color;import java.awt.Graphics;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import javax.swing.JPanel;import javax.swing.Timer;/** * 五子棋的面板 * @author jackfrued * */@SuppressWarnings("serial")public class RenjuPanel extends JPanel { private Timer timer = null; private Board b = new Board(); // 创建棋盘对象 private boolean isBlack = true; // 是否黑方走棋 private boolean gameBegin = false; // 游戏是否开始 public RenjuPanel() { this.setSize(620, 620); this.addMouseListener(new MouseAdapter() { // 添加鼠标事件监听器监听鼠标按下事件 @Override public void mousePressed(MouseEvent e) { if(gameBegin) { int x = e.getX(); int y = e.getY(); if(x >= 20 && x <= 600 && y >= 20 && y <= 600) { int row = Math.round((y - 30) / 40.0f); int col = Math.round((x - 30) / 40.0f); if(b.move(row, col, isBlack)) { // 在鼠标点击位置走棋 isBlack = !isBlack; repaint(); } } } } }); timer = new Timer(1500, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int row = (int) (Math.random() * 15); int col = (int) (Math.random() * 15); if(b.move(row, col, isBlack)) { isBlack = !isBlack; repaint(); } } }); timer.start(); } @Override public void paint(Graphics g) { super.paint(g); // 绘制背景 g.setColor(Color.ORANGE); g.fillRect(0, 0, 620, 620); // 绘制棋盘 g.setColor(Color.BLACK); b.draw(g); } /** * 重置五子棋面板 */ public void reset() { timer.stop(); b.reset(); isBlack = true; gameBegin = true; }}
package com.lovoinfo;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Graphics;import java.awt.Graphics2D;/** * 棋盘 * @author jackfrued * */public class Board { private static final int CELL_SIZE = 40; private CellState[][] board = new CellState[15][15]; private int lastRow = -1, lastCol = -1; public Board() { reset(); } /** * 走棋 * @param row 落子的行 * @param col 落子的列 * @param isBlack 是不是黑棋 * @return 如果落子成功返回true否则返回false */ public boolean move(int row, int col, boolean isBlack) { if(board[row][col] == CellState.Empty) { board[row][col] = isBlack? CellState.Black : CellState.White; lastRow = row; lastCol = col; return true; } return false; } /** * 绘制棋盘和棋子 * @param g 画笔 */ public void draw(Graphics g) { // 纵横15道 for(int i = 0; i < board.length; i++) { g.drawLine(30, 30 + CELL_SIZE * i, 590, 30 + CELL_SIZE * i); g.drawLine(30 + CELL_SIZE * i, 30, 30 + CELL_SIZE * i, 590); } g.fillOval(305, 305, 10, 10); // 天元 Graphics2D g2d = (Graphics2D) g; g2d.setStroke(new BasicStroke(3)); // 将画笔变粗 g.drawRect(25, 25, 570, 570); // 外边框 // 对棋盘的行和列进行循环绘制棋子 for(int i = 0; i < board.length; i++) { for(int j = 0; j < board[i].length; j++) { if(board[i][j] != CellState.Empty) { // 不是空白 Color color = board[i][j] == CellState.Black? Color.BLACK : Color.WHITE; g.setColor(color); g.fillOval(10 + CELL_SIZE * j, 10 + CELL_SIZE * i, CELL_SIZE, CELL_SIZE); } } } if(lastRow != -1 && lastCol != -1) { g.setColor(Color.RED); g.drawLine(25 + CELL_SIZE * lastCol, 30 + CELL_SIZE * lastRow, 35 + CELL_SIZE * lastCol, 30 + CELL_SIZE * lastRow); g.drawLine(30 + CELL_SIZE * lastCol, 25 + CELL_SIZE * lastRow, 30 + CELL_SIZE * lastCol, 35 + CELL_SIZE * lastRow); } } /** * 重置棋盘 */ public void reset() { lastRow = -1; lastCol = -1; for(int i = 0; i < board.length; i++) { for(int j = 0; j < board[i].length; j++) { board[i][j] = CellState.Empty; } } }}
package com.lovoinfo;public enum CellState { Empty, Black, White}
0 0
- 【连载】Java学习系列(008)——深入面向对象-2
- 【连载】Java学习系列(006)——面向对象入门
- Java基本知识(连载)-深入面向对象
- 深入Java系列——面向对象之(一)——抽象
- java学习系列1(面向对象)
- 【连载】Java学习系列(004)——程序逻辑-2(分支和循环)
- java语言学习连载(四)--深入理解面象对象
- OC语言第一课 面向对象、类、对象、方法一 ——ios学习连载六
- OC语言第二课 面向对象、类、对象、方法二——ios学习连载七
- 【连载】Java学习系列(001)——Java概述和基本语法
- Java面向对象深入
- 面向对象——封装、继承、多态——ios学习连载八
- 【连载】Java学习系列(003)——程序逻辑-1(分支和循环)
- 【连载】Java学习系列(002)——数据类型和常用运算
- 【连载】Java学习系列(005)——数组、方法和字符串
- 【连载】Java学习系列(007)——继承和多态
- javascript 面向对象深入学习-----(一)
- Java基本知识(连载)-面向对象入门
- [C语言][数据结构]基础的线性表的顺序表示和实现
- 例题6-3 矩阵连乘(栈)UVa 442
- 检测机器的CPU的字节序(Big Endian OR Little Endian)
- 第五届在线编程大赛月赛第一题:完全平方数的个数
- webService 路径
- 【连载】Java学习系列(008)——深入面向对象-2
- Win7 AERO主题变成灰色解决方法
- https://leetcode.com/problems/zigzag-conversion/
- Java基本概念与问题(三)
- java开发环境搭建
- [刷题]Minimum Path Sum
- leetcode 104 Maximum Depth of Binary Tree二叉树求深度
- Intent的详细介绍
- 编程之美---求数组的子数组之和的最大值