# Tank
**Repository Path**: inspiration666/tank
## Basic Information
- **Project Name**: Tank
- **Description**: 坦克大战,设计模式
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-06-08
- **Last Updated**: 2022-08-12
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 坦克大战
## 一、23种设计模式
> 讲解设计模式概念与应用
### 1.单例模式
#### I.常规用法
```java
/**
* 饿汉式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 简单实用,推荐使用!
* 唯一缺点:不管用到与否,类装载时就完成实例化
* Class.forName("")
* (话说你不用的,你装载它干啥)
*/
public class Mgr01 {
private static final Mgr01 INSTANCE = new Mgr01();
private Mgr01() {};
public static Mgr01 getInstance() {
return INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
Mgr01 m1 = Mgr01.getInstance();
Mgr01 m2 = Mgr01.getInstance();
System.out.println(m1 == m2);
}
}
```
#### II.优化用法
> 静态内部类方式,JVM保证单例加载外部类时,不会加载内部类,这样可以实现懒加载
```java
/**
* 静态内部类方式
* JVM保证单例
* 加载外部类时不会加载内部类,这样可以实现懒加载
*/
public class Mgr07 {
private Mgr07() {
}
private static class Mgr07Holder {
private final static Mgr07 INSTANCE = new Mgr07();
}
public static Mgr07 getInstance() {
return Mgr07Holder.INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
for(int i=0; i<100; i++) {
new Thread(()->{
System.out.println(Mgr07.getInstance().hashCode());
}).start();
}
}
}
```
#### III.大神写法(了解)
> 不仅可以解决线程同步,还可以防止反序列化
```java
/**
* 不仅可以解决线程同步,还可以防止反序列化。
*/
public enum Mgr08 {
INSTANCE;
public void m() {}
public static void main(String[] args) {
for(int i=0; i<100; i++) {
new Thread(()->{
System.out.println(Mgr08.INSTANCE.hashCode());
}).start();
}
}
}
```
### 2.策略模式
> 打出不同的子弹
### 3.工厂模式
> 创建不同的爆炸、子弹、坦克
- 简单工厂:生产单个产品
- 说明:抽象工厂用来生产多个产品
> 什么时候用接口?什么时候用抽象类?
答:形容词用接口,名词用抽象类,比如:可移动的用接口,飞机用抽象类(飞机下面还有客机、侦察机等)
### 4.抽象工厂
> 生产多个产品
### 5.门面(Facade)模式(外观模式)
> GameModel类管理画图、制造坦克;Model(坦克、子弹、爆照)和View(画图)分离,注意区分:**GameModel对于TankFrame来说是门面,对于GameObject来说是调停者**
### 6.中介(Mediator)模式(调停者模式)
> 所有物体(坦克、子弹、爆炸)继承抽象类GameObject,当需要再添加一个物体的时候,比如墙,直接继承GameObject抽象类,方便GameModel(中介/调停者)管理
### 7.责任链模式
> 不同物体之间的碰撞后是不同的效果,即不同的责任,使用ColliderChain将其串起来,可实现责任链模式,更深层次的,ColliderChain也可实现Collider接口,之后也可以实现更多类似ColliderChain的类
### 8.装饰器模式
> 给子弹增加一些装饰,比如方框和线条;装饰器模式使用率很低,使用率高的设计模式有:**责任链、代理模式、工厂模式、策略模式、观察者模式**,这些必须掌握
### 9.观察者模式
> 事件处理模型(观察者+责任链),坦克大战里的按键监听器就是用的观察者模式
### 10.组合模式
> 专门用于处理树状结构
### 11.享元模式
> 重复利用对象(享元:共享元对象)
### 12.代理模式(Proxy)
> 静态代理、动态代理、spring AOP
### 13.迭代器模式(Iterator)
> 一个用来遍历容器的专用的设计模式,如ArrayList、LinkedList中的iterator()方法
### 14.访问者模式(Visitor)
> 在结构不变的情况下动态改变对于内部元素的动作。多数情况用于编译器上,使用ASM动态修改字节码时就用到了访问者模式(章节12-3)
>
> 另外:
>
> jdk动态代理和cglib动态代理底层都用的ASM
### 15.Builder(构建器、建造者模式)
> 用于构建复杂对象。对于构造参数类型很多的对象,使用该模式可以更方便的建造不同构造参数类型的对象(属性分组),【考虑:读取key-value配置文件可以用这个模式吗?】
### 16.适配器模式(Adapter(Wrapper))
> 接口转换器
### 17.Bridge(桥接模式)
> 双维度扩展。
- 分离抽象与具体
- 用聚合方式(桥)连接抽象与具体
### 18.Command(命令模式,别名:Action/Transaction)
> 封装命令,结合责任链模式实现undo(撤销)
### 19.Prototype(原型模式、克隆模式)
- java自带
- 实现原型模式需要实现标记型接口(没有方法实现)Cloneable
- 一般会重写clone()方法
- 如果支持重写clone()方法,而没实现接口,调用时会报异常
- 一般用于一个对象的属性已经确定,需要产生很多相同对象时候
- 需要区分深克隆和浅克隆
### 20.Memento(备忘录模式)
> 记录状态,便于回滚。实战:按S键实现当前坦克状态存盘、按L键实现回滚到存盘状态(需要序列化对象)
### 21.TemplateMethod(模版方法)
> 钩子函数。凡是重写一个方法,系统帮我们自动调用的都可以称为模版方法。如ASM中的ClassVisitor中国visitMethod、visitCode等。
### 22.State状态模式
> 根据状态决定行为(14-3)
- 场景(并非使用了state设计模式):线程状态迁移图(有限状态机-FSM)
> 
- 使用起来像策略模式(个人观点)
### 23.Intepreter解释器
> 动态脚本解析。只做了解
### 总结
> 
### 指导思想
- 可维护性Maintainability
- 修改功能,需要改动的地方越少,可维护性就越好
- 可复用性Reusability
- 代码可以被以后重复使用
- 写出自己总结的类库
- 可扩展性Extensibility/Scalability
- 添加功能无需修改原来代码
- 灵活性felxibility/mobility/adaptability
- 代码接口可以灵活调用
### 面向对象六大原则
#### 1.单一职责原则-SRP
- Single Responsibility Principle
- 一个类别太大,别太累,只负责单一的职责
- Person
- PersonManager
- 高内聚,低耦合
#### 2.开闭原则-OCP
- Open-Closed Principle
- 对扩展开放,对修改关闭
- 尽量不修改原来代码的情况下进行扩展
- 抽象化,多态是开闭原则的关键
#### 3.里氏替换原则-LSP
- Liscov Substitution Principle
- 所有使用父类的地方,必须能够透明的使用子类
#### 4.依赖倒置原则-DIP
- Dependency Inversion Principle
- 依赖倒置原则
- 依赖抽象(接口),而不是依赖具体
- 面向抽象(接口)编程
> 如F f=new FImpl();
>
> 编程时只需使用接口f暴露的方法
#### 5.接口隔离原则-ISP
- Interface Segregation Principle
- 每一个接口应该承担独立的角色,不干不该自己干的事
- 如Flyable Runnable不该合二为一
- 避免子类实现不需要实现的方法
- 需要对客户提供接口的时候,只需要暴露最小的接口
#### 6.迪米特法则-LoD
- Law of Demeter
- 尽量不要和陌生人说话
- 在迪米特法则中,对于一个对象,非陌生人包括以下几类:
- 当前对象本身(this);
- 以参数形式传入到当前对象方法中的对象;
- 当前对象的成员对象;
- 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;
- 当前对象所创建的对象。
- 和其他类的耦合度变低
附录:
[opengameart游戏资源网站](https://opengameart.org/)