day26设计模式(单例模式&简单工厂模式&工厂方法模式)&网络编程(UDP协议&TCP协议)

设计模式

    1、创建型  创建对象
    2、结构型  对象的组成
    3、行为型  对象的功能

创建型模式:
    1、单例模式
        指的是在程序运行过程中,内存中只允许一个对象存在
        饿汉式
        懒汉式
    2、简单工厂模式
    3、工厂方法模式

        创建型的第一种:
            单例模式:保证在内存中只存在一个对象
            1、将构造方法私有化
            2、在类的成员变量的位置上创建一个对象
            3、提供一个公共的静态方法让外界获取到这个对象

        饿汉式:类一加载,就创建对象

package com.shujia.wyh.day26.shejimoshi.danli;

public class StudentDemo {
    public static void main(String[] args) {
        Student s1 = Student.getStudent();
        Student s2 = Student.getStudent();
        System.out.println(s1==s2); //true 同一个对象
    }
}

class Student {
    private static Student student = new Student();

    private Student(){}

    public static Student getStudent(){
        return student;
    }
}

        懒汉式:用的时候,再去创建对象,但是内存中始终只有一个对象
            1、懒加载(延迟加载)
            2、容易产生线程安全问题
                1) 在存在多线程环境中,只允许出现一个对象的类是共享数据
                2) 并且有多条语句操作着共享数据
                3) 需要使用锁来解决线程安全问题

package com.shujia.wyh.day26.shejimoshi.danli;

public class TeacherDemo {
    public static void main(String[] args) {
        Teacher t1 = Teacher.getTeacher();
        Teacher t2 = Teacher.getTeacher();
        System.out.println(t1==t2);

    }
}

class Teacher {
    private Teacher() {
    }

    private static Teacher t = null;

    //静态的同步方法
    public synchronized static Teacher getTeacher() {
        if (t == null) {
            t = new Teacher();
        }
        return t;
    }

}

    简单工厂模式(静态工厂方法模式)

    优点:
        客户端不需要负责创建对象,从而明确了各个类的职责

    缺点:
        我们定义的静态工厂类负责对象的创建,如果有新的对象增加
        获取某些对象的创建方式不同,就需要不断的去修改工厂类,不利于后期维护

package com.shujia.wyh.day26.shejimoshi.easyfactory;

public class AnimalDemo {
    public static void main(String[] args) {
        Animal dog = AnimalFactory.createAnimal("Dog");
        Animal cat = AnimalFactory.createAnimal("Cat");
        if(dog!=null){
            dog.eat();
        }

        if(cat!=null){
            cat.eat();
        }

        Animal pig = AnimalFactory.createAnimal("Pig");
        if(pig!=null){
            pig.eat();
        }
    }
}

class AnimalFactory {
    //构造方法私有化,让外界无法创建该类的实例
    private AnimalFactory(){}

    //使用多态的形式修改
    public static Animal createAnimal(String type){
        if("Cat".equals(type)){
            return new Cat();
        }else if("Dog".equals(type)){
            return new Dog();
        }else {
            System.out.println("该工厂不支持创建"+type+"类型的动物");
            return null;
        }
    }
}

abstract class Animal {
    public abstract void eat();
}

class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("🐕吃🥩");
    }
}

class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("🐱吃🐟");
    }
}

             工厂方法模式的优缺点:
            优点:
                客户端不需要负责对象的创建,从而明确各个类的职责
                如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可
                不影响其他的代码,后期容易维护,增强了系统的扩展性。
            缺点:
                需要额外的写代码,增加了工作量

package com.shujia.wyh.day26.shejimoshi.factoryFunction;

public class AnimalDemo {
    public static void main(String[] args) {
        //我想要只狗
        DogFactory dogFactory = new DogFactory();
        Animal dog = dogFactory.createAnimal();
        dog.eat();

        //我想要只猫
        CatFactory catFactory = new CatFactory();
        Animal cat = catFactory.createAnimal();
        cat.eat();

        //我想要只猪
        PigFactory pigFactory = new PigFactory();
        Animal pig = pigFactory.createAnimal();
        pig.eat();

    }
}

abstract class Animal {
    public abstract void eat();
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("🐕吃🥩");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("🐱吃🐟");
    }
}

class Pig extends Animal{
    @Override
    public void eat() {
        System.out.println("🐖吃饲料");
    }
}

//创建工厂接口,具体工厂类实现接口
interface Factory {
    public abstract Animal createAnimal();
}

class DogFactory implements Factory{
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}

class CatFactory implements Factory{
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}

class PigFactory implements Factory{
    @Override
    public Animal createAnimal() {
        return new Pig();
    }
}

网络编程

网络通信三要素

IP地址:InetAddress     网络中设备的标识,不易记忆,可用主机名

端口号     用于标识进程的逻辑地址,不同进程的标识

传输协议     通讯的规则     常见协议:TCP,UDP

        InetAddress类

                获取任意主机:getByName                  

                主机名:getHostName       

                主机Ip地址:getHostAddress

package com.shujia.wyh.day26.network;

import java.net.InetAddress;

public class InetAddressDemo {
    public static void main(String[] args) throws Exception {
        InetAddress name = InetAddress.getByName("192.168.7.42");
        System.out.println(name);

        //public String getHostName()获取此IP地址的主机名
        String hostName = name.getHostName();
        System.out.println(hostName);

        //public String getHostAddress()返回文本显示中的IP地址字符串。
        String address = name.getHostAddress();
        System.out.println(address);
    }
}

     UDP协议发送数据:
           1、创建发送端的Socket对象
           2、创建数据,并把数据打包
           3、调用Socket对象的发送方法将数据发送出去
           4、释放资源,关闭Socket

package com.shujia.wyh.day26.network;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class SendDemo2 {
    public static void main(String[] args) throws Exception {
        //1、创建发送端的Socket对象
        DatagramSocket ds = new DatagramSocket();

        //2、键盘录入数据
        Scanner sc = new Scanner(System.in);
        String next = sc.next();
        BufferedReader br = new BufferedReader(new InputStreamReader(next));

        String line = null;
        while ((line=br.readLine())!=null){
            if("886".equals(line)){
                break;
            }

            //如果输入的数据不是886,将数据打包发送出去
            DatagramPacket packet = new DatagramPacket(line.getBytes(), line.getBytes().length,
                    InetAddress.getByName("192.168.7.42"), 12345);

            //调用Socket对象中发送数据包的方法
            ds.send(packet);
        }

        //释放资源
        ds.close();


    }
}

 UDP协议接收数据:
  1、创建接收端的Socket对象
  2、创建一个数据包(接收容器)、
  3、调用Socket对象的接收方法接收数据
  4、解析数据包,得到数据并显示在控制台上
  5、释放资源,关闭Socket

  注意事项:
       接收端程序在绑定同一个端口的时候不能同时运行多个

package com.shujia.wyh.day26.network;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class ReceiveDemo1 {
    public static void main(String[] args) throws Exception {
        //1、创建接收端的Socket对象
        //DatagramSocket(int port)
        //构造数据报套接字并将其绑定到本地主机上的指定端口。
        DatagramSocket ds = new DatagramSocket(12345);

        //2、创建一个数据包(接收容器)
        //定义个字节数组
        byte[] bytes = new byte[1024];
        int length = bytes.length;
        //DatagramPacket(byte[] buf, int length)
        //构造一个 DatagramPacket用于接收长度的数据包 length 。
        DatagramPacket datagramPacket = new DatagramPacket(bytes, length);

        //3、调用Socket对象的接收方法接收数据
        ds.receive(datagramPacket); //程序阻塞,直到接收到数据

        String ip = datagramPacket.getAddress().getHostAddress();
        String hostName = datagramPacket.getAddress().getHostName();

        //4、解析数据包,得到数据并显示在控制台上
        //public byte[] getData()返回数据缓冲区。
        byte[] data = datagramPacket.getData();
        //public int getLength()返回要发送的数据的长度或接收到的数据的长度。
        int length1 = datagramPacket.getLength();
        String s = new String(data, 0, length1);
        System.out.println(ip + ":" + hostName + "发送的数据为:" + s);

        //释放资源,关闭Socket
        ds.close();


    }
}

    TCP协议客户端代码实现:
        1、创建客户端的Socket对象
            这一步如果成功创建对象,就说明连接已经建立成功
        2、获取输出流对象,向服务器写数据
        3、释放资源,关闭Socket服务

    注意事项:
        要先启动服务器端,再启动客户端,否则会报连接被拒绝异常

package com.shujia.wyh.day26.network;

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientDemo3 {
    public static void main(String[] args) throws Exception {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);

        //创建客户端Socket对象
        Socket s = new Socket("192.168.7.42", 12345);
        System.out.println("请输入想要发送的数据:");

        //获取通道中字节输出流对象
        OutputStream os = s.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os);
        BufferedWriter bw = new BufferedWriter(osw);

        while (true){
            String next = sc.next();
            if("886".equals(next)){
                s.shutdownOutput();
                break;
            }

            bw.write(next);
            bw.newLine();
            bw.flush();
        }

        s.close();

    }
}

       TCP协议编写服务器端代码:
           1、创建服务器端Socket对象(ServerSocket)
           2、调用accept()方法,监听客户端的连接,返回一个对应客户端连接的Socket对象
           3、获取通道中的输入流对象,读取客户端发送的数据,并显示在控制台上
           4、释放资源,关闭Socket服务

package com.shujia.wyh.day26.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ServerDemo3 {
    public static void main(String[] args) throws Exception {
        System.out.println("================服务器启动=======================");
        //创建服务器端自身的Socket对象
        ServerSocket ss = new ServerSocket(12345);

        //监听的时候,对应一个客户端,返回一个对应的Socket对象
        //定义一个循环不断的接收客户端的连接请求
        while (true){
            //开始接收客户端与服务器端之间连接
            Socket socket = ss.accept();
            new ServerReaderThread(socket).start();

        }
    }
}

//定义与客户端连接连接操作的线程类
class ServerReaderThread extends Thread{
    private Socket socket;

    ServerReaderThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        //获取与客户端通道中的字节输入流对象
        try {

            InputStream is = socket.getInputStream();
            //将字节输入流对象包装成字符流
            InputStreamReader isr = new InputStreamReader(is);
            //使用字符缓冲输入流
            BufferedReader br = new BufferedReader(isr);
            //ip
            String ip = socket.getInetAddress().getHostAddress();
            String hostName = socket.getInetAddress().getHostName();

            //按照行来读取
            String line;
            while ((line=br.readLine())!=null){
                //获取当前时间
                Date date = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String date2 = sdf.format(date);
                System.out.println(date2);
                System.out.println(ip+":"+hostName+"发送来数据:"+line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值