# 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) > ![1656820494979](site/images/1656820494979.png) - 使用起来像策略模式(个人观点) ### 23.Intepreter解释器 > 动态脚本解析。只做了解 ### 总结 > ![1656824780138](site/images/1656824780138.png) ### 指导思想 - 可维护性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/)