黑马程序员-Java设计模式

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

目录:
1. 生成器模式
2. 策略模式
3. 模板模式
4. 工厂模式
5. 装饰模式
6. 享元模式
7. 单例模式


1. 生成器模式(Builder Pattern)

例如下面的Student类,实例字段很多,这样如果在构造器中创建一个对象的话非常的麻烦,需要传入多达7个参数。遇到这种场景,我们可以使用构造器模式来优化对象的创建。

public class Student {
    private final String name;
    private final int age;
    private final int number;
    private final String major;
    private final String address;
    private String email;
    private int phone;

    public Student(private String name, private int age, private int number, private String major,private  String address, private String email, private int phone) {
    super();
    this.name = name;
    this.age = age;
    this.number = number;
    this.major = major;
    this.address = address;
    this.email = email;
    this.phone = phone;
    }
}

在构造器模式中,原来的类的创建任务被委托到一个伴随类中,例如下面是一个简单的构造器模式的使用,它改进了上面的Student类的创建。
在Student类中定义了一个内部类Builder,它包含了外部类的所有字段,调用Builder类的withXXX方法可以对参数进行设置,由于这些方法返回了构建者本身,所以可以采用’链式’编程。最后调用build方法可以创建一个外围类对象,build方法内部调用了外围类的构造方法,并把参数传递给构造器,最后返回这个对象。

public class Student {
    private final String name;
    private final int age;
    private final int number;
    private final String major;
    private final String address;
    private String email;
    private long phone;

    public static class Builder {
        private String name;
        private int age;
        private int number;
        private String major;
        private String address;
        private String email;
        private long phone;

        // 伴随方法,返回构建者,可以采用'链式'编程
        public Builder withName(final String name) {
            this.name = name;
            return this;
        }

        public Builder withAge(final int age) {
            this.age = age;
            return this;
        }

        public Builder withNumber(final int number) {
            this.number = number;
            return this;
        }

        public Builder withMajor(final String major) {
            this.major = major;
            return this;
        }

        public Builder withAddress(final String address) {
            this.address = address;
            return this;
        }

        public Builder withEmail(final String email) {
            this.email = email;
            return this;
        }

        public Builder withPhone(final long phone) {
            this.phone = phone;
            return this;
        }

        // 伴随类创建Student类对象的方法,方法中首先对必须设置的参数进行检查,如果符合条件,那么调用Student类的构造方法,创建一个对象,如果不符合抛出异常。
        public Student build() throws IllegalStateException {
            if (name != null && age != 0 && number != 0 && major != null && address != null) {
                return new Student(name, age, number, major, address, email, phone);
            } else {
                throw new IllegalStateException("cannot create Pet");
            }
        }

    }

    // 构造方法设置为私有权限,只能通过伴随类来调用
    private Student(final String name, final int age, final int number, final String major, final String address, final String email, final long phone) {
        super();
        this.name = name;
        this.age = age;
        this.number = number;
        this.major = major;
        this.address = address;
        this.email = email;
        this.phone = phone;
    }

    public static void main(String[] args) {
        //测试,创建构造器对象
        Student.Builder builder = new Builder();
        Student xiaoming = builder
            .withName("xiaoming")
            .withNumber(250)
            .withMajor("Math")
            .withAddress("Beijing")
            .build();
    }

}

2. 策略模式(Strategy Pattern)

使用策略模式可以很方便的替换某个算法的具体实现,而不需要重写代码。
代码示例:
下面的日志记录器中,存在两个具体实现,一个将日志消息打印到控制台,另一个将消息保存到文件中。

//用于日志记录的接口
public interface Logging {
    public abstract void write(String msg);
}

//实现了Logging接口的ConsoleLogging日志记录类,它将日志消息打印到控制台
public class ConsoleLogging implements Logging {

    @Override
    public void write(String msg) {
        System.out.println(msg);
    }

}

//实现了Logging接口的日志记录类,它将日志消息保存到文件中
public class FileLogging implements Logging {
    // 用于保存日志的本地文件
    private File location;

    public FileLogging(File location) throws IOException {
                this.location = location;
    }

    @Override
    public void write(String msg) {
        // 打印流,用于将数据写入文件,使用try-with-resources语句确保资源关闭
        try (PrintWriter pw = new PrintWriter(new FileWriter(location, true), true)) {
            pw.println(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

在下面的简单测试中,我们可以方便的替换日志记录器的具体实现:

public class Test {
    public static void main(String[] args) throws IOException {

        Logging log = new ConsoleLogging();
        //可以把日志记录器替换为保存到文件中的实现
        //log = new FileLogging(new File("d:\\testLogging.txt"));

        for (int i = 0; i < 100; i++) {
            if (i % 3 == 0) {
                //记录100以内的能被3整除的int类型整数
                log.write("" + i);
            }
        }
    }
}

3. 模板模式(Template Pattern)

模板模式是把一个算法的部分或全部步骤推出或委托给一个子类。公共的行为在超类中定义。

代码示例:
下面的StringList类中定义了一个包含字符串的列表,包含一个过滤方法,传入一个
StringFilter对象,就能对字符串列表进行过滤并返回过滤后的列表。StringFilter是一个接口,它实现了模板模式,我们可以定义不同的过滤功能。

需要注意的是,filter方法中,遍历了字符串列表的每一个元素,然后根据一个谓词判断元素的值是否应该包含在被返回的列表中。这个方法把过滤算法的判断步骤委托给StringFilter对象,它把判定某个值的逻辑和过滤字符串列表算法完全分离开了。

import java.util.LinkedList;
import java.util.List;

public class StringList {
    private List<String> list;

    public StringList(List<String> list) {
        this.list = list;
    }

    public List filter(StringFilter filter) {
        List<String> toReturn = new LinkedList<String>();
        for (String element : list) {
            if (filter.isValid(element))
                toReturn.add(element);
        }

        return toReturn;
    }

}

//这是一个模板,定义了一个判断字符串是否满足条件的方法,子类可以定义具体的行为
public interface StringFilter {
    boolean isValid(String str);
}

下面演示了使用模板的两种实现,一种什么也不做,直接返回true;另一个方法根据字符串的长度判断,如果大于3则返回true。

import java.util.LinkedList;
import java.util.List;

public class StringListTest {
    public static void main(String[] args) {

        //定义一个字符串列表
        List<String> list = new LinkedList<String>();
        list.add("java");
        list.add("android");
        list.add("ios");
        list.add("c");
        list.add("windows");
        list.add("sql");

        // 创建一个测试对象
        StringList sl = new StringList(list);
        //使用匿名内部类的模板实现
        StringFilter nonFilter = new StringFilter() {

        // 没有过滤任何东西
        @Override
        public boolean isValid(String str) {
            return true;
        }

        };
        //测试
        List test1 = sl.filter(nonFilter);
        //使用lambda expression遍历列表,发现没有过滤任何元素
        test1.forEach(element -> System.out.println(element));
        //另一个模板实现,根据字符串长度进行过滤
        StringFilter lengthFilter = new StringFilter() {

            // 字符串长度超过3的才能返回true
            @Override
            public boolean isValid(String str) {
                if (str.length() > 3)
                    return true;
                return false;
            }

        };

        List test2 = sl.filter(lengthFilter);
        //结果打印了三个字符串长度大于3的元素
        test2.forEach(element -> System.out.println(element));
    }
}

在上例中,将模板中的算法分离开来有很多好处,使用者可以根据具体的要求来实现它,同时又不需要对StringList类作任何的修改。

4. 工厂模式

工厂模式是将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化而不必知道每次要实例化哪一个类。它分为简单工厂模式、工厂方法模式和抽象工厂模式三种。下面具体介绍:

(1)简单工厂模式
简单工厂模式又称为静态方法模式,属于类创建型模式。由于工厂模式比较复杂,这里介绍下它包含的三个角色:

  • 工厂类(核心):用于创建其他类的实例,包含判断逻辑以判断要创建哪一个具体类;
  • 抽象产品类:工厂类创建的所有产品的超类或他们共同的接口;
  • 具体产品类:工厂方法创建的具体产品实例。

代码示例:
下面的示例中Factory 是工厂类,包含了创建Car实例的静态方法;Car接口是抽象产品类,定义了公共功能;Vw和Bmw是具体的产品类,工厂模式创建的所有产品都是他们的实例:

public class Factory {
    public static Car makeCar(String carName) {
        if (carName.equalsIgnoreCase("vw")) {
            return new Vw();
        }
        if (carName.equalsIgnoreCase("bmw")) {
            return new Bmw();
        } else
            return null;
    }
}

public interface Car {
    void drive();
}

public class Vw implements Car {

    @Override
    public void drive() {
        System.out.println("正在开一辆大众汽车");
    }

}

public class Bmw implements Car {

    @Override
    public void drive() {
        System.out.println("正在开一辆宝马汽车");
    }

}

简单工厂模式适合创建的类比较少的场景,因为他所有的产品判断逻辑都包含在工厂的静态方法中。在增加产品时,需要增加一个具体产品类和修改工厂方法的判断逻辑。在使用的时候,客户端无需知道具体产品类和创建细节,只需要提供参数即可。

(2)工厂方法模式

该模式中定义了一个工厂类接口,包含一个创建对象的抽象方法。通过子类来决定生产哪一种具体产品。在工厂方法模式中,核心的工厂类不再创建具体产品,而是把工作交给子类,核心类只提供接口。

工厂方法模式包含的角色:

  • 抽象工厂类:工厂模式中的任何工厂类都要实现它,定义了创建产品的公共方法;
  • 具体工厂类:实现了抽象工厂的具体工厂类。含有创建产品的实例方法;
  • 抽象产品类:工厂类创建的所有产品的超类或他们共同的接口;
  • 具体产品类:工厂方法创建的具体产品实例。

下面的示例中,Factory 是抽象工厂类,Car是抽象产品类,Bmw 和Vw是具体的产品类,BmwFactory和VwFactory 是对应的工厂类 :

public interface Factory {
    Car makeCar();
}

public interface Car {
    void drive();
}

public class Bmw implements Car {

    @Override
    public void drive() {
        System.out.println("正在开一辆宝马汽车");
    }

}

public class Vw implements Car {

    @Override
    public void drive() {
        System.out.println("正在开一辆大众汽车");
    }

}

public class BmwFactory implements Factory {

    @Override
    public Car makeCar() {
        return new Bmw();
    }

}

public class VwFactory implements Factory {

    @Override
    public  Car makeCar() {
        return new Vw();
    }

}

在下面的测试中,我们使用了工厂类来创建对象。可以看到多态特性是具体工厂类的能创建对应的产品的关键。

public class CarMakeTest {

    public static void main(String[] args) {
        Factory bmwFactory=new BmwFactory();
        Car bmw=bmwFactory.makeCar();
        bmw.drive();

        Factory vwFactory=new VwFactory();
        Car vwCar=vwFactory.makeCar();
        vwCar.drive();

    }

}

(5)装饰模式(Decorator Pattern)

装饰模式就是给原有的对象修改或配置功能。装饰模式中,装饰者和被装饰的对象都应实现同一个接口。使用装饰模式可以进行功能的组装,例如JavaIO中就大量应用了装饰模式,比如我们可以把一个输入文件字节流对象传入一个缓冲字节流中组合成带有缓冲输出功能的文件字节流。

    File toOpen=new File("d:\\anyFile");
    FileOutputStream fos=new FileOutputStream(toOpen);//文件字节输出流
    BufferedOutputStream bos=new BufferedOutputStream(fos);//缓冲字节输出流

具体代码:
下面的Book是一个接口,被装饰类NoteBook和装饰类ColorBook 都实现了这个接口,最后在装饰类的main测试方法中演示了使用装饰模式创建一个ColorBook 实例的步骤。

public interface Book {
    void write();
}

public class NoteBook implements Book{

    @Override
    public void write() {
        System.out.println("book");
    }

}

public class ColorBook implements Book {

    private Book target;

    public ColorBook(Book target) {
        super();
        this.target = target;
    }

    @Override
    public void write() {
        System.out.print("white ");
        target.write();
    }

    public static void main(String[] args) {
        Book b=new NoteBook();
        b.write();//原始方法打印结果:book
        ColorBook cb=new ColorBook(b);
        cb.write();//装饰后的方法打印结果:white book  }

}

6. 享元模式(Flyweight Pattern)

享元模式适用于多个对象共享一个值的情况。它的前提是对象的值不可变,否则一个对象修改值后所有共享该值的变量都会受到影响。
Java中使用了享元模式的有String类、基本类型包装类如Integer等。下面使用Integer来介绍享元模式。

Integer类型比较特殊,他包含一个int范围在-128~127的常量池,即Integer对象表示的int类型数值在-128~127之间时,会直接从常量池中返回,而不会新建Integer对象。

代码示例:
下面使用代码来证明常量池的存在,需要注意的是使用valueOf方法才会使用常量池中的数据,使用new关键字则是新建一个对象。下面第三组证明了这一点。

public class Test {
    public static void main(String[] args) {
        //常量池中的引用直接返回
        Integer i1 = Integer.valueOf(127);
        Integer i2 = Integer.valueOf(127);
        System.out.println(i1 == i2);//true
        //常量池有范围
        Integer i3 = Integer.valueOf(128);
        Integer i4 = Integer.valueOf(128);
        System.out.println(i3 == i4);//false
        //使用构造器不会用到常量池
        Integer i5=new Integer(127);
        Integer i6=new Integer(127);
        System.out.println(i5 == i6);//false

    }
}

7. 单例模式(Singleton Pattern)

单例模式是指一个类只允许创建一个实例,下面是一个具体示例。

public class SingletonPattern {
    //私有化构造器
    private SingletonPattern() {}
    //提供一个静态SingletonPattern类的类字段,初始化为空,当客户端调用获取方法后才实例化,这种方式成为迟加载,可以减少对象的创建,提升性能
    private static SingletonPattern alone = null;
    //提供静态的获取单例对象的方法,注意该方法必须使用同步机制对共享的变量alone进行保护,同时进行了迟加载方法,只有在第一次调用该方法时,类变量alone才会初始化
    public static synchronized SingletonPattern getInstance() {
        if (alone == null) {
            alone = new SingletonPattern();
            return alone;
        } else {
            return alone;
        }
    }

    public static void main(String[] args) {
        //测试成功创建
        SingletonPattern myInstance = SingletonPattern.getInstance();
    }
}

由于单例类对象的获取方法采用了同步方法,这样在频繁获取对象的时候会降低性能,所以可以考虑把创建过程分离开,并只对它进行同步保护。下面是改进后的代码:

public class SingletonPattern {
    private SingletonPattern() {
    }

    private static SingletonPattern alone = null;

    public static SingletonPattern getInstance() {
        if (alone == null) {
            initSingle();
            return alone;
        } else {
            return alone;
        }
    }

    // 初始化alone变量的同步方法,只会被调用一次
    private synchronized static void initSingle() {
        if (alone == null)
            alone = new SingletonPattern();
    }

    public static void main(String[] args) {
    // 测试成功创建
    SingletonPattern myInstance = SingletonPattern.getInstance();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员 设计模式c 是指黑马程序员通过C语言实现设计模式的一门课程。设计模式是面向对象设计中经过实践和总结后的一种解决问题的方案。它是一种具体的设计思路,是编写高质量、易于理解、可维护和可扩展的代码的指导原则。在软件开发中,我们经常会遇到各种各样的问题,设计模式可以帮助我们更加灵活高效地解决这些问题。 黑马程序员设计模式C课程从理论讲解到实践操作,通过C语言来实现各种设计模式,帮助学员理解设计模式的原理和应用场景。通过学习该课程,学员可以提升自己的设计能力和编程水平,使得自己编写的代码更加优雅和可复用。 该课程主要包括以下几个部分:首先是介绍设计模式的基本概念和分类;然后是详细讲解每一种设计模式的原理、结构和应用场景;接着是通过具体的案例来演示如何在C语言中实现每一种设计模式;最后是实际项目实战,让学员能够将所学的设计模式应用到实际的软件开发中。 通过学习黑马程序员设计模式C课程,可以帮助开发人员更好地理解和应用设计模式,提高软件开发的质量和效率。无论是对于初学者还是有一定经验的开发人员来说,都可以从中获得实际的收益。设计模式是编写高质量代码的基石,掌握设计模式可以让我们在编程过程中更加得心应手,实现代码的可维护性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值