坦克大战 - 设计模式、BIO、NIO、AIO、Netty
設計模式
1、策略模式
有時候你想發射單排子彈,有時候你想發射雙排子彈。
當你想有不同的子彈發射方式時,應該怎么做才能在盡可能少的修改代碼的前提下,快速完成這些子彈發射策略的切換呢?
辦法就是,你寫一個Interface,讓不同的策略去實現這個Interface。
你去通過配置文件,選擇你想要的子彈發射方式。
在子彈發射邏輯中,通過反射獲取策略對應的類,然后直接調用接口的實現方法。
2、責任鏈模式
責任鏈模式,類似于 Servlet 的 Filter
在坦克大戰游戲中,你怎么判斷兩個游戲物體的碰撞?通過 if - else 暴力遍歷嗎?這樣不好,因為如果你想加入新的規則,對代碼的改動太大了。
使用碰撞器
你可以寫很多種不同的碰撞器(碰撞規則),每一個碰撞器是一個獨立的類,去實現Collider接口。
然后,通過每一個collider的返回值,控制當前的鏈條是否要繼續。(如果在當前碰撞器中已經發生了碰撞,則后面的鏈條就不需要執行了)
你比如說,子彈、坦克相撞的碰撞器可以這樣定義:
寫完很多碰撞器之后,怎么在邏輯中檢測是否發生了各種碰撞之一呢?
你可以通過編寫配置文件,在邏輯中反射獲取所有你需要加載的碰撞器,放在一個list里面(colliders是一個list)
通過遍歷這個裝有各種碰撞器的list,去檢測每一種碰撞是否發生。
用這種方式,當你想要添加新的碰撞規則時,你只需要在碰撞器包下,新建一個碰撞器,然后在配置文件中把新的碰撞器添加進去,就可以啦。代碼就會變得非常靈活,擴展方便。
3、Facade 門面模式
根據MVC,進行Model和View的分離,寫一個GameModel類,將來所有的Model都可以放在GameModel中
4、Mediator 調停者模式
如果你有非常復雜的業務邏輯(比如說在我們的坦克大戰中,坦克坦克碰撞,坦克子彈碰撞,子彈和墻碰撞,…),這時候我們專門給這些復雜的業務邏輯單獨寫一個調停者。
網絡模型
TCP的模型有下面三種:BIO,NIO,AIO
1、BIO
BIO 是阻塞式的 IO,需要等待。
- 等待客戶端的連接,連接后,會拋出一個線程
- 等待客戶端發送消息
服務端:
package com.bjmashibing.system.io;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket;public class SocketServer {public static void main(String[] args) throws Exception {ServerSocket server = new ServerSocket(9090, 20);while (true) {Socket client = server.accept(); //阻塞1,等待客戶端連接,連接后拋出一個線程new Thread(() -> {InputStream in = null;try {in = client.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(in));while (true) {String dataline = reader.readLine(); //阻塞2,等待客戶端發來消息if (null != dataline) {System.out.println(dataline);} else {client.close();break;}}System.out.println("客戶端斷開");} catch (IOException e) {e.printStackTrace();}}).start();}} }客戶端:
package com.bjmashibing.system.io;import java.io.*; import java.net.Socket;/*** @author: 馬士兵教育* @create: 2020-05-17 16:18*/ public class SocketClient {public static void main(String[] args) {try {Socket client = new Socket("192.168.150.11", 9090);client.setSendBufferSize(20);client.setTcpNoDelay(true);OutputStream out = client.getOutputStream();InputStream in = System.in;BufferedReader reader = new BufferedReader(new InputStreamReader(in));while (true) {String line = reader.readLine();if (line != null) {byte[] bb = line.getBytes();for (byte b : bb) {out.write(b);}}}} catch (IOException e) {e.printStackTrace();}} }2、NIO (Non Blocking IO)
非阻塞式的,叫ServerSocket
非阻塞式的,叫ServerSocketChannel
3、AIO
AIO 是異步的模型,使用的是 callback / hook / templateMethod 回調,是基于事件模型的 IO
AIO只有Window支持(內核中使用CompletionPort完成端口),而在Linux上的AIO只不過是對NIO的封裝而已(是基于epoll的輪詢)。
所以Netty封裝的是NIO
使用線程組的AIO
package com.mashibing.io.aio;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousChannelGroup; import java.nio.channels.AsynchronousServerSocketChannel; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class ServerWithThreadGroup {public static void main(String[] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool();AsynchronousChannelGroup threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);//中文測試final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(threadGroup).bind(new InetSocketAddress(8888));serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {@Overridepublic void completed(AsynchronousSocketChannel client, Object attachment) {serverChannel.accept(null, this);try {System.out.println(client.getRemoteAddress());ByteBuffer buffer = ByteBuffer.allocate(1024);client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {attachment.flip();System.out.println(new String(attachment.array(), 0, result));client.write(ByteBuffer.wrap("HelloClient".getBytes()));}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {exc.printStackTrace();}});} catch (IOException e) {e.printStackTrace();}}@Overridepublic void failed(Throwable exc, Object attachment) {exc.printStackTrace();}});while (true) {Thread.sleep(1000);}} }4、Nettty
Netty主要用于網絡通信。很多網頁游戲的服務器都是用Netty寫的。
Tomcat,Zookeeper,很多開源分布式的底層都是netty寫的。
總結
以上是生活随笔為你收集整理的坦克大战 - 设计模式、BIO、NIO、AIO、Netty的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 左神算法课笔记(一):时间复杂度、排序、
- 下一篇: 左神算法课笔记(二):链表、栈和队列、递