day25 Java 设计模式 网络编程


I know, i know
地球另一端有你陪我




一、设计模式

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


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

    优点
        客户端不需要在负责对象的创建,从而明确了各个类的职责
    缺点
        这个静态工厂类负责所有对象的创建,如果有新的对象增加,
        或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护
 */
public class AnimalDemo {
    
    
    public static void main(String[] args) {
    
    
        //改进版
        Animal dog = AnimalFactory.createAnimal("Dog");
        dog.eat();
        Animal cat = AnimalFactory.createAnimal("Cat");
        cat.eat();

        Animal pig = AnimalFactory.createAnimal("Pig");
        if(pig!=null){
    
    
            pig.eat();
        }else {
    
    
            System.out.println("该工厂目前还不提供制造该对象的功能!");
        }
    }
}

总抽象类 Animal

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

实现类 Cat

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

实现类 Dog

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

静态工厂方法类

public 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 {
    
    
            return null;
        }
    }
}

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

/*
工厂方法模式

    优点
        客户端不需要在负责对象的创建,从而明确了各个类的职责,
        如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,
        不影响已有的代码,后期维护容易,增强了系统的扩展性
    缺点
        需要额外的编写代码,增加了工作量
 */
public class AnimalDemo {
    
    
    public static void main(String[] args) {
    
    
        //我想要只狗
        DogFactory dogFactory = new DogFactory();
        Animal animal = dogFactory.creatCreateAnimal();
        animal.eat();

        //我想要只猫
        CatFactory catFactory = new CatFactory();
        Animal animal1 = catFactory.creatCreateAnimal();
        animal1.eat();
    }
}

总抽象类 Animal

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

实现类 Cat

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

实现类 Dog

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

猫猫工厂

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

狗狗工厂

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

3、单例模式(饿汉式、懒汉式)

饿汉式

/*
        单例模式:保证在类中只存在一个对象

        如何保证类在内存中只有一个对象?
            1、构造方法私有
            2、在类的成员变量的位置上创建一个对象
            3、提供一个公共的方法给外界获取到该对象

        通过观察发现,我们随着类一加载,对象就创建好了
        这样的方法是,单例模式中的饿汉式。
 */
public class StudentDemo {
    
    
    public static void main(String[] args) {
    
    
        Student s1 = Student.getStudent();
        Student s2 = Student.getStudent();

        System.out.println(s1==s2);
        System.out.println(s1);
        System.out.println(s2);
    }
}
public class Student {
    
    
    private static Student s = new Student();
    
    private Student(){
    
    
    }
    public static Student getStudent(){
    
    
        return s;
    }
}

懒汉式

/*
        如何保证类在内存中只有一个对象?
            1、构造方法私有
            2、在类的成员变量的位置上创建一个对象
            3、提供一个公共的方法给外界获取到该对象

        饿汉式:类一加载,就创建对象
        懒汉式:用的时候,再去创建对象。
            1、懒加载(延迟加载)
            2、容易产生线程安全问题
                1)是否存在多线程环境 是
                2)是否存在共享变量 是
                3)是否存在多条语句操作共享变量
 */
public class TeacherDemo {
    
    
    public static void main(String[] args) {
    
    
        Teacher t1 = Teacher.getTeacher();
        Teacher t2 = Teacher.getTeacher();

        System.out.println(t1==t2);
        System.out.println(t1);
        System.out.println(t2);
    }
}
public class Teacher {
    
    
    private Teacher(){
    
    
    }

    private static Teacher t = null;
    
    //静态同步方法
    public synchronized static Teacher getTeacher(){
    
    
            //t1,t2,t3
            if(t == null){
    
    
                t = new Teacher();
            }
            return t;
        }
}

二、网络编程

就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换
在这里插入图片描述
网络通信三要素

IP地址
InetAddress,网络中设备的标识,不易记忆,可用主机名
端口号
用于标识进程的逻辑地址,不同进程的标识
传输协议
通讯的规则,常见协议:TCP,UDP


三、协议 UDP & TCP

1、UDP

将数据源和目的封装成数据包中,不需要建立连接;
每个数据报包的大小在限制在64k;因无连接,是不可靠协议;
不需要建立连接,速度快

UDP协议接收端接收数据:

        1、创建接收端的Socket对象
        2、创建一个接收包(接收数据容器)
        3、调用Socket的接收方法接收数据  receive()
        4、解析数据包,获取数据,显示在控制台
        5、释放资源,关闭Socket
public class Receive1 {
    
    

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

        //指定可以接收的字节数组大小
        byte[] bytes = new byte[1024];
        int length = bytes.length;

        //DatagramPacket(byte[] buf, int length)
        //构造一个 DatagramPacket用于接收长度的数据包 length
        DatagramPacket dp = new DatagramPacket(bytes, length);

        //public void receive(DatagramPacket p)
        //调用Socket的接收方法接收数据
        //该方法阻塞,直到接收到数据包
        ds.receive(dp);

        //public InetAddress getAddress()
        // 返回该数据报发送或接收数据报的计算机的IP地址。
        InetAddress address = dp.getAddress();

        //解析数据包,获取数据
        //public byte[] getData()返回数据缓冲区
        byte[] data = dp.getData();

        //public int getLength()
        // 返回要发送的数据的长度或接收到的数据的长度
        int length1 = dp.getLength();

        String s = new String(data, 0, length1);
        System.out.println(address+":"+s);

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

UDP协议发送端发送数据

   		1、建立发送端的Socket对象
    	2、创建数据,并将数据打包
    	3、通过调用Socket的发送方法将数据包发出去
    	4、释放资源,关闭Socket
public class Send1 {
    
    

    public static void main(String[] args) throws Exception{
    
    
        //建立UDP发送端的Socket对象DatagramSocket
        //DatagramSocket()
        //构造数据报套接字并将其绑定到本地主机上的任何可用端口
        DatagramSocket ds = new DatagramSocket();

        byte[] bytes = "韭菜盒子".getBytes();
        int length = bytes.length;

        //指定发送端的IP地址    /192.168.2.151
        InetAddress address = InetAddress.getByName("192.168.2.151");

        //端口号
        //有效端口:0~65535,其中0~1024系统使用或保留端口
        int port = 2222;

        //创建数据
        //DatagramPacket(byte[] buf, int length, 
        //							InetAddress address, int port)
        //构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
        DatagramPacket dp = new DatagramPacket(bytes,length,address,port);

        //void send(DatagramPacket p)
        //从此套接字发送数据报包
        ds.send(dp);

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


    }
}

2、TCP

建立连接,形成传输数据的通道;在连接中进行大数据量传输;
通过三次握手完成连接,是可靠协议;
必须建立连接,效率会稍低

TCP协议接收数据服务器端

    	1、创建服务器端的Socket对象 ServerSocket
    	2、监听客户端连接,返回一个对应的客户端的Socket对象
   		3、获取输入流对象,读取数据,显示在控制台上
    	4、释放资源
    	
    	        还未启动服务器就启动客户端报错:
        	java.net.ConnectException: Connection refused: connect
        		连接被拒绝

    		TCP协议一定要先启动服务器
public class Server1 {
    
    

    public static void main(String[] args) throws Exception{
    
    

        //创建服务器端的Socket对象 ServerSocket
        //ServerSocket(int port)
        //创建绑定到指定端口的服务器套接字
        ServerSocket ss = new ServerSocket(5555);

        //监听客户端连接,返回一个对应的客户端的Socket对象
        //public Socket accept()
        // 侦听要连接到此套接字并接受它
        //该方法将阻塞直到建立连接
        Socket accept = ss.accept();

        //获取输入流对象,读取数据,显示在控制台上
        //public InputStream getInputStream()
        //返回此套接字的输入流
        InputStream is = accept.getInputStream();
        byte[] bytes = new byte[1024];
        int length = is.read(bytes);

        String s = new String(bytes, 0, length);

        //获取谁发送的信息,IP
        //public InetAddress getInetAddress()返回套接字所连接的地址。
        //返回客户端的地址
        InetAddress ia = accept.getInetAddress();

        System.out.println(ia+":"+s);

        //释放资源
        accept.close();
    }
}

TCP协议传输发送数据端

    	1、创建客户端的Socket对象
        	指定服务器的IP和端口,内部自动建立连接
        	一旦建立连接成功,说明与服务IO通道形成
    	2、获取输出流,往IO通道写数据
    	3、释放资源
public class Client1 {
    
    

    public static void main(String[] args) throws Exception{
    
    

        Socket s = new Socket("192.168.2.151",5555);

        //获取输出流
        //public OutputStream getOutputStream()
        //返回此套接字的输出流
        OutputStream os = s.getOutputStream();
        os.write("韭菜盒子耶".getBytes());

        //释放资源
        s.close();
    }
}

总结

UDP:不需要建立连接

服务器端
1、new DatagramSocket (int port)
指定接口,建立连接

2、new DatagramPacket (byte[] buf, int length)
创建包,用于接收数据

3、receive(DatagramPacket p)
接收数据

4、getData ()
获取数据

5、close ()
释放资源

发送端
1、new DatagramSocket ()
建立连接

2、new DatagramPacket(byte[] buf, int length, InetAddress address, int port)
创建数据包

3、send(DatagramPacket p)
发送数据包

4、close ()
释放资源

TCP:建立连接,三次握手
注:需要先建立服务器端确定接口号

服务器端
1、new ServerSocket (int port)
指定端口号,创建服务器连接

2、accept ()
监听客户端连接,知道获取发送端数据前,为阻塞状态

3、getInputStream () getInetAddress()
获取输入流,读取发送端的数据 / ip地址

4、close ()
释放资源

发送端
1、Socket (String host, int port)
创建客户端借口,指定接收端的 ip 和端口号

2、getOutputStream()
获取输出流,写入发出信息

3、close ()
释放资源

おすすめ

転載: blog.csdn.net/qq_41464008/article/details/120958100