常用设计模式+作业题

一.常用设计模式

1.概述

A:设计模式概述
		设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编写、代码设计经验的总结。
		使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性以及代码的结构更加清晰.
	B:设计模式分类
		创建型模式(创建对象的):	单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
		行为型模式(对象的功能):	适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
		结构型模式(对象的组成):	模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。

2.简单工厂模式

	A:简单工厂模式概述:	又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
	B:优点:	使用静态工厂模式的优点是实现责任的分割,该模式的核心是工厂类,工厂类含有必要的选择逻辑,可以决定什么时候创建哪一个产品的实例,
			而客户端则免去直接创建产品的责任,而仅仅是消费产品。也就是说静态工厂模式在不改变客户端代码的情况可以动态的增加产品。
			明确了类的职责
	C:缺点
		这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,
		就需要不断的修改工厂类,不利于后期的维护
package org.westos.demo2;

public abstract class Animal {
    public abstract void eat();
}
--------
package org.westos.demo2;

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

public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
--------
package org.westos.demo2;

public class Tiger extends Animal{
    //新加入一个动物
    @Override
    public void eat() {
        System.out.println("老虎吃大米");
    }
}
-----
package org.westos.demo2;

//工厂类
public class AnimalFactory {
    //主要负则创建动物实例

    private AnimalFactory() {
    }
    //创建猫的实例
    public static Cat getCat(){
        return new Cat();
    }
    public static Dog getDog(){
        return new Dog();
    }
    //新加入一个Tiger,增加一个方法
    //每增加一个产品,就要增加一个方法来提供一个类的实例
    public static Tiger getTiger(){
        return new Tiger();
    }

    //优化
    public static Animal getAnimal(String name){
        if ("cat".equals(name)){
            return new Cat();
        }else if ("dog".equals(name)){
            return new Dog();
        }else if ("tiger".equals(name)){
            return new Tiger();
        }else {
            return null;
        }
    }
}
---------
package org.westos.demo2;

public class MyTest {
    public static void main(String[] args) {
        //既要负则创建,又要负则使用
        //工厂模式指的是只关心使用而不关心创建,把创建部分交由工厂来实现
        /*Dog dog = new Dog();
        dog.eat();

        Cat cat = new Cat();
        cat.eat();*/

        Dog dog = AnimalFactory.getDog();
        Cat cat = AnimalFactory.getCat();
        dog.eat();
        cat.eat();

        Animal animal = AnimalFactory.getAnimal("cat");
        animal.eat();
        animal = AnimalFactory.getAnimal("dog");
        animal.eat();
        animal = AnimalFactory.getAnimal("tiger");
        animal.eat();


    }
}

3.工厂方法模式

	A:工厂方法模式概述
		工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现。
	B:优点
		客户端不需要在负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,
		只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
	C:缺点:	需要额外的编写代码,增加了工作量
package org.westos.demo3;

public interface BigFactory {
    //只有一个方法,创建产品的方法
   Animal createAnimal();
}
------
package org.westos.demo3;

public abstract class Animal {
    public abstract void eat();
}
------
package org.westos.demo3;

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

public class CatFactory implements BigFactory{
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}
------
package org.westos.demo3;

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
------
package org.westos.demo3;

public class DogFactory implements BigFactory{
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}
------
package org.westos.demo3;

import org.westos.demo3.Animal;

public class Tiger extends Animal {
    //新加入一个动物
    @Override
    public void eat() {
        System.out.println("老虎吃大米");
    }
}
------
package org.westos.demo3;

public class TigerFactory implements BigFactory{
    @Override
    public Animal createAnimal() {
        return new Tiger();
    }
}
-----
package org.westos.demo3;

public class MyTest {
    public static void main(String[] args) {
        DogFactory dogFactory = new DogFactory();
        Animal animal = dogFactory.createAnimal();
        animal.eat();

        Animal animal2 = new CatFactory().createAnimal();
        animal2.eat();
        //有新产品增加,不用改原有的代吗,只是在增加代码,增加了一个工厂和创建类
        Animal animal3 = new TigerFactory().createAnimal();
        animal3.eat();
    }
}

4.单例模式之懒汉式

单例:保证一个类的对象,在内存中只有一个
步骤:
1.私有构造,不能在外界直接new对象
2.提供静态方法返回一个该类的实例供外界使用
3.加入synchronized关键字保证多线程环境下的使用也是单例的
package org.westos.demo4;

public class MyTest {
    public static void main(String[] args) {
        //单列:保证一个类的对象,在内存中只有一个
        //Student student = new Student();
        Student studen = Student.getStuden();
        Student studen1 = Student.getStuden();
        System.out.println(studen==studen1);
    }
}
----------
package org.westos.demo4;

public class Student {

    //1.私有构造,不能在外界直接new对象
    //懒汉式:使用时再去创建,延迟加载
    private Student() {
    }

    private static Student student=null;

    //2.提供静态方法返回一个该类的实例供外界使用
    //加入synchronized关键字保证多线程环境下的使用也是单例的
    public synchronized static Student getStuden(){
        //不能保证对象唯一
        if (student==null) {
            //Thread.sleep(20);
            student= new Student();
        }
        return student;
    }
}

5.单例模式之饿汉式

1.这个类一加载,我就创建一个该类的对象
2.私有化构造
3.提供静态方法返回一个该类的实例供外界使用
package org.westos.demo5;

public class MyTest {
    public static void main(String[] args) {
        Teacher teacher = Teacher.getTeacher();
        Teacher teacher1 = Teacher.getTeacher();
        System.out.println(teacher==teacher1);
    }
}
-----
package org.westos.demo5;

public class Teacher {//Teacher.class
    //饿汉式,这个类一加载,我就创建一个该类的对象
    private static Teacher teacher=new Teacher();
    //饿汉式
    //保证Teacher类的实例在内存中只有一份
    //1.私有化构造

    private Teacher() {
    }
    //2.提供静态方法返回一个该类的实例供外界使用
    //不存在多线程安全问题,因为teacher是静态的,只加载一次,随着类的加载而加载
    //只new了一次,多线程仍是单例
    public static Teacher getTeacher(){
        return teacher;
    }

}

6.单例模式之Runtime类

A:Runtime类概述
		每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。 
		应用程序不能创建自己的 Runtime 类实例。
B:public Process  exec(String command)  //执行Dos 命令
	C:查看Runtime的源码:		发现是单例模式的应用
package org.westos.demo6;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MyTest {
    public static void main(String[] args) throws IOException, ParseException {
        // Runtime 类采用的是单列模式的饿汉式
        Runtime runtime = Runtime.getRuntime();
        //打开计算器
        runtime.exec("calc");
        //打开画图
        runtime.exec("mspaint");

        //定时关机
        String str="2020-06-10 11:20:00";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(str);

        Timer timer = new Timer();
        MyTimerTask myTimerTask = new MyTimerTask(timer);
        timer.schedule(myTimerTask,date);
    }
}
class MyTimerTask extends TimerTask{
    private Timer timer;
    public MyTimerTask(Timer timer) {
        this.timer = timer;
    }

    @Override
    public void run() {
        Runtime runtime = Runtime.getRuntime();
        try {
            runtime.exec("shutdown /s /t 0");
            timer.cancel();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

7.模版设计模式

A:模版设计模式概述
		模版方法模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现
	B:优点和缺点
		a:优点:	使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求
		b:缺点:	如果算法骨架有修改的话,则需要修改抽象类
package org.westos.demo7;

public abstract class CalcClass {

    public void calc(){
        long start = System.currentTimeMillis();
        //CalcFor();
       // CalcCopyFiles();
        //算法骨架未变
        calcAll();
        long end = System.currentTimeMillis();
        System.out.println("耗时"+(end-start)+"毫秒");
    }

    private void CalcFor() {
    /*
    //1.计算for循环的耗时
    for (int i = 0; i < 1000; i++) {
        System.out.println(i);
    }
    */
    }
    private void CalcCopyFiles(){
        //2.复制文件
        System.out.println("复制文件");
    }
    public abstract void calcAll();
}
-------
package org.westos.demo7;

public class CalcFor extends CalcClass{
    @Override
    public void calcAll() {
        //算法骨架已经写好,只需要写需要执行的操作
        for (int i = 0; i < 100; i++) {
            System.out.println("aaa");
        }
    }
}
------
package org.westos.demo7;

public class CopyFile extends CalcClass{
    @Override
    public void calcAll() {
        System.out.println("复制文件");
    }
}
----
package org.westos.demo7;

public class MyTest {
    public static void main(String[] args) {
        //1.计算for循环的耗时
        //new CalcClass().calc();
        CalcClass calcFor = new CalcFor();
        calcFor.calc();

        calcFor=new CopyFile();
        calcFor.calc();

    }
}

8.装饰模式

A:装饰模式概述:	装饰模式就是使用被装饰类的一个子类的实例,在客户端将这个子类的实例交给装饰类。是继承的替代方案
	B:优点和缺点
		a:优点
			使用装饰模式,可以提供比继承更灵活的扩展对象的功能,它可以动态的添加对象的功能,
			并且可以随意的组合这些功能。
		b:缺点:	正因为可以随意组合,所以就可能出现一些不合理的逻辑。
package org.westos.demo8;

//包装类:对某个类的功能进行增强
public class BZPhone implements Phone{
    private Phone phone;

    //你要包装哪个类,把那个类传过来
    public BZPhone(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void call() {
        this.phone.call();
    }
}
--------
package org.westos.demo8;

public class GamePhone extends BZPhone{
    public GamePhone(Phone phone) {
        super(phone);
    }

    @Override
    public void call() {
        super.call();
        System.out.println("打游戏");
    }
}
-------
package org.westos.demo8;

public class IPhone implements Phone{
    public void call(){
        System.out.println("打电话");

    }
}
-------
package org.westos.demo8;

public class MusicPhone extends BZPhone{
    public MusicPhone(Phone phone) {
        super(phone);
    }

    @Override
    public void call() {
        super.call();
        System.out.println("听歌");
    }
}
-------
package org.westos.demo8;

public class MyTest {
    public static void main(String[] args) {
        IPhone iPhone = new IPhone();
        iPhone.call();
        System.out.println("==========");
        //拓展功能:找一个包装类
        //你要包装哪个类,把那个类传过来
        MusicPhone musicPhone = new MusicPhone(iPhone);
        musicPhone.call();
        System.out.println("==========");
        VideoPhone videoPhone = new VideoPhone(iPhone);
        videoPhone.call();
        System.out.println("==========");

        VideoPhone videoPhone1 = new VideoPhone(new MusicPhone(iPhone));
        videoPhone1.call();
        System.out.println("==========");
        MusicPhone musicPhone1 = new MusicPhone(new VideoPhone(iPhone));
        musicPhone1.call();
        System.out.println("=========");
        MusicPhone musicPhone2 = new MusicPhone(new GamePhone(iPhone));
        musicPhone2.call();
        System.out.println("========");
        MusicPhone musicPhone3 = new MusicPhone(new GamePhone(new VideoPhone(iPhone)));
        musicPhone3.call();
    }
}
-----
package org.westos.demo8;

public interface Phone {
    void call();
}
-------
package org.westos.demo8;

public class VideoPhone extends BZPhone{
    public VideoPhone(Phone phone) {
        super(phone);
    }

    @Override
    public void call() {
        super.call();
        System.out.println("看视频的功能");
    }
}

9.观察者模式

 观察者 = 订阅者 + 发布者
	     岗位类  求职者  猎头(注册方法,注销方法,发布方法)

package org.westos.demo9;

import java.util.ArrayList;

public class Hunter {
    //放求职者
    private ArrayList<JobSeeker> jobSeekers=new ArrayList<>();
    //放工作岗位
    private ArrayList<Job> jobs=new ArrayList<>();

    //求职者注册
    public void addJobSeeker(JobSeeker jobSeeker){
        jobSeekers.add(jobSeeker);
    }
    //注册工作岗位
    public void addJob(Job job){
        jobs.add(job);
        //有适合求职者的工作岗位,通知求职者
        notifyJobSeeker(job);
    }

    private void notifyJobSeeker(Job job) {
        for (JobSeeker jobSeeker : jobSeekers) {
            System.out.println(jobSeeker.getName()+"有适合你的工作"+job.getJobName()+
                    "薪资"+job.getSale()+"欢迎前来面试");
        }
    }

    //注销求职者
    public void removeJobSeeker(JobSeeker jobSeeker){
        jobSeekers.remove(jobSeeker);
    }

}
-----
package org.westos.demo9;

public class Job {
    private String jobName;
    private Double sale;

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    public Double getSale() {
        return sale;
    }

    public void setSale(Double sale) {
        this.sale = sale;
    }

    public Job(String jobName, Double sale) {
        this.jobName = jobName;
        this.sale = sale;
    }


    public Job() {
    }
}
----
package org.westos.demo9;

public class JobSeeker {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public JobSeeker(String name) {
        this.name = name;
    }
}
------
package org.westos.demo9;

public class MyTest {
    public static void main(String[] args) {
        //观察者 = 订阅者 + 发布者

        JobSeeker j1 = new JobSeeker("张三");
        JobSeeker j2 = new JobSeeker("李白");
        JobSeeker j3 = new JobSeeker("杜甫");

        //在猎头出注册
        Hunter hunter = new Hunter();
        hunter.addJobSeeker(j1);
        hunter.addJobSeeker(j2);
        hunter.addJobSeeker(j3);

        Job job = new Job("文员",1000.0);
        hunter.addJob(job);
        System.out.println("====");
        Job job1 = new Job("Java开发", 10000.0);
        hunter.addJob(job1);
        System.out.println("=======================");

        //注销
        hunter.removeJobSeeker(j1);
        Job job2 = new Job("前端", 999.9);
        hunter.addJob(job2);

    }
}

二.作业题

1.把一个文件复制多份

package org.westos.demo;

import java.io.*;

public class MyTest {
    public static void main(String[] args) throws IOException {
        //把一个文件复制多份
        RandomAccessFile in = new RandomAccessFile("a.txt","rw");
        int len=0;
        byte[] bytes = new byte[1024*8];
        for (int i = 0; i < 3; i++) {
            //用i来给文件命名
            FileOutputStream out = new FileOutputStream(i + ".txt");
            while ((len=in.read(bytes))!=-1){
                out.write(bytes,0,len);
                out.flush();
            }
            //重新设置指针
            in.seek(0);
            out.close();
        }
        in.close();
    }
}

2.判断键更改值

        需求:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。
        请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”
package org.westos.demo;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class MyTest3 {
    public static void main(String[] args) throws IOException {
         /*
        需求:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。
        请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”*/

        Properties properties = new Properties();
        //把文本中的键值对读取到集合中
        properties.load(new FileReader("b.txt"));

        if (properties.containsKey("lisi")){
            //键相同,值覆盖
            properties.put("lisi","100");

            properties.store(new FileWriter("b.txt"),null);
        }else {
            System.out.println("错误,不存在该键");
        }


    }
}

3.文件的拆分合并

package org.westos.demo;

import java.io.*;
import java.util.Enumeration;
import java.util.Vector;

public class MyTest4 {
    public static void main(String[] args) throws IOException {
        //文件的拆分
        //chaiFen();
        //文件的合并
        heBing();
    }

    public static void heBing() throws IOException{
        //music文件夹里放的是拆分完的文件
        File srcFolder = new File("C:\\Users\\user\\Desktop\\music");
        Vector<InputStream> vector = new Vector<>();
        File[] files = srcFolder.listFiles();
        for (File f : files) {
            if (f.length()<=1024*1024&&f.getName().endsWith(".mp3")){
                FileInputStream in = new FileInputStream(f);
                vector.add(in);
            }
        }
        Enumeration<InputStream> elements = vector.elements();
        SequenceInputStream sequenceInputStream = new SequenceInputStream(elements);

        FileOutputStream out = new FileOutputStream("C:\\Users\\user\\Desktop\\222.mp3");
        int len=0;
        byte[] bytes = new byte[1024 * 8];
        while ((len=sequenceInputStream.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        sequenceInputStream.close();
        out.close();

        //合并完成,删除拆分的文件
        for (File f : srcFolder.listFiles()) {
            if (f.length() <= 1024 * 1024 && f.getName().endsWith(".mp3")) {
                f.delete();
            }
        }
    }
    public static void chaiFen() throws IOException{
        //把一个文件,拆成多份,每份一M 然后再合并回去
        //将拆分的文件夹放到music文件夹里
        File file = new File("C:\\Users\\user\\Desktop\\music");
        if (!file.exists()) {
            file.mkdirs();
        }
        File src = new File("C:\\Users\\user\\Desktop\\陈一发儿01 - 童话镇.mp3");
        FileInputStream in = new FileInputStream(src);
        int len=0;
        byte[] bytes = new byte[1024 * 1024];
        int count=0;
        while ((len=in.read(bytes))!=-1){
            count++;
            FileOutputStream out = new FileOutputStream(new File(file,count+".mp3"));
            out.write(bytes,0,len);
            out.close();
        }
        in.close();

    }
}

4.多个线程共同复制一个文件

package org.westos.demo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;

public class MyTest5 {
    public static void main(String[] args) throws FileNotFoundException {
        //多个线程复制同一个文件
        //封装源文件
        File srcFile = new File("C:\\Users\\user\\Desktop\\陈一发儿01 - 童话镇.mp3");
        //获取文件大小
        long length = srcFile.length();
        //定义线程的数量
        long threadNum =3;
        //计算机每个线程平均要复制的字节大小
        long pj = length / threadNum;

        //计算每个线程复制的那部分字节数据的起始位置和结束位置
        for (long i = 0; i < threadNum; i++) {
            //0---100
            //101---200
            //201---300
            long start = pj * i;
            long end = (i + 1) * pj - 1;
            //System.out.println("线程"+i+"起始位置:"+start+"结束位置:"+end);
            //开启线程复制
            new CopyFileThread(start, end, srcFile, new File("C:\\Users\\user\\Desktop\\3.mp3")).start();
        }
        //文件的大小,不够多个线程均分,如310
        //解决办法是,如果不够均分,我就在补一个线程,把剩下的复制完
        if (length % threadNum != 0) {
            System.out.println("不均分");
            long start = threadNum * pj;
            long end = length;
            //System.out.println("补得线程"+"起始位置:" + start + "结束位置:" + end);
            new CopyFileThread(start, end, srcFile, new File("C:\\Users\\user\\Desktop\\3.mp3")).start();
        }

    }
}
class CopyFileThread extends Thread {
    private long start;
    private long end;
    private RandomAccessFile in;
    private RandomAccessFile out;
    /*
     start      每个线程复制的起始位置
     end        每个线程复制的结束位置
     srcFile    源文件
     targetFile 目标文件
     */

    public CopyFileThread(long start, long end,  File srcFile, File targetFile) throws FileNotFoundException {
        this.start = start;
        this.end = end;
        this.in = new RandomAccessFile(srcFile, "rw");
        this.out = new RandomAccessFile(targetFile, "rw");
    }

    @Override
    public void run() {

        try {
            //设置读写起始指针
            in.seek(start);
            out.seek(start);
            //如果是一个字节一个字节来复制, start < end 那就隔离了
            //如果说你的缓冲区不是一个字节 start < end 逻辑上隔离 最后一次,可能会多写会覆盖 不影响

            int len = 0;
            byte[] bytes = new byte[1024*8];
            while ((start<end)&&((len=in.read(bytes))!=-1)){
                start+=len;
                out.write(bytes,0,len);
            }
            in.close();
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值