文章目录
java设计模式
设计模式常用的七大原则:
- 单一职责原则;
- 接口隔离原则;
- 依赖倒转原则;
- 里氏替换原则;
- 开闭原则ocp;
- 迪米特法则;
- 合成复用原则;
设计模式概述
1:设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式不是代码,而是某类问题的通用解决方案,设计模式代表了最佳的实践。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
2:设计模式的本质提高 软件的维护性,通用性和扩展性,并降低软件的复杂度。
设计模式分为三种类型,共23种
- 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式;
- 结构性模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式;
- 行为型模式:模板方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)。
一、单例模式
单例模式: 采取一定的方法保证一个类仅有一个实例,该类负责创造自己的唯一实例,这个类提供了一种访问其唯一实例的方式,可以直接访问,不需要实例化该类对象。
特点: ①只有一个实例;
②自我实例化;
③提供全局访问点(静态方法)直接用类调用方法,便可获得该类的唯一实例。
1、饿汉模式(静态常量)
步骤:
- 构造器私有化;
- 类的内部创建对象;
- 向外暴露一个静态的公共方法:getInstance
类加载时就初始化
public class Singleton{
//1:构造器私有化,外部能new
private Singleton(){
}
//让构造函数为private,这样该类就不会被实例化
//2:本类内部创建对象实例
private static Singleton instance = new Singleton();
//3:提供一个共有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
- 这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快;
- 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。
2、饿汉模式(静态代码块)
public class Singleton{
//1:构造器私有化,外部能new
private Singleton(){
}
//2:本类内部创建对象实例
private static Singleton instance;
static{//在静态代码块中,创建单例对象
instance = new Singleton();
}
//3:提供一个共有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
- 这种方法和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也就是类装载的时候,就执行静态代码块中的代码,初始化类的实例。有缺点和上面是一样的;
- 结论,可以用,但有可能造成内存浪费。
3、懒汉模式(非线程安全)
public class Singleton{
private static Singleton instance;
//让构造函数为private,这样该类就不会被实例化
private Singleton(){}
//提供一个静态的公有方法,当使用该方法时,才去创建instance;即懒汉式
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
- 懒汉模式申明了一个静态对象,在用户第一次调用时初始化,后面的调用都返回同一个对象,虽然节约了资源,但第一次调用时需要实例化,但反应稍微慢一些,而且不是线程安全的。
4、懒汉模式(线程安全)
public class Singleton{
private static Singleton instance;
//让构造函数为private,这样该类就不会被实例化
private Singleton(){}
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题,及懒汉式
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
- 线程安全的懒汉模式使用了synchronized关键字,所以是线程安全的;
- 效率太低了,每次调用getInstance方法都需要进行线程同步,造成不必要的同步开销,而且大部分时候是用不到同步的,所以不建议使用这种模式。
5:懒汉模式(线程安全,同步代码块)
public class Singleton{
private static Singleton instance;
//让构造函数为private,这样该类就不会被实例化
private Singleton(){}
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题,及懒汉式
public static Singleton getInstance(){
if(instance == null){
synchronized(instance.class){
instance = new Singleton();
}
}
return instance;
}
}
二、工厂模式
1、简单的工厂模式
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。定义了一个创建对象的类,由这个类来封装实例化对象的行为。在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用工厂模式。
简单的工厂模式: 一个工厂类根据传入的参数决定创建出哪一种产品类的实例;
应用场景: 创建一个可以绘制不同形状的绘图工具,可以绘制圆形、正方形、长方形、三角形等,每个图形都会以一个draw()方法用于绘图。
创建过程: 编写具体的图形,每种图形都是Shape接口
class Rectangle implements Shape {
@Override
public void draw(){
System.out.println("Inside Rectangle::draw() method.");
}
}
class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle1::draw() method.");
}
}
public interface Shape{
void draw();
}
创建一个工厂类,基于给定信息的实体类对象
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public static Shape getShape(String shapeType){
Shape shape = null;
if(shapeType.equalsIgnoreCase("CIRCLE")){
shape = new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
shape = new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
shape = new Square();
}
return shape;
}
}
- 为所有的产品先创建一个抽象类或接口,然后通过实现抽象类或接口创建具体的产品类;
- 创建工厂类,工厂类中有一个get方法,可以通过传入的产品名称创建并返回具体的产品对象;
- 使用时,通过调用工厂类的get方法并传入产品名称,便可以获得具体的产品对象。
2、工厂模式
- 工厂模式是简单工厂的进一步深化,在工厂模式中,不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂,也就是说每个对象都有一个与之对应的工厂。
创建过程: ①首先完成加载器的设计,在编写一个加载器的公共接口;
public interface Reader {
void read();
}
②编写具体的加载类,每次加载器都是Reader接口;
public class JpgReader implements Reader {
@Override
public void read() {
System.out.print("read jpg");
}
}
public class PngReader implements Reader {
@Override
public void read() {
System.out.print("read png");
}
}
public class GifReader implements Reader {
@Override
public void read() {
System.out.print("read gif");
}
}
③定义一个抽象的工厂接口ReaderFactory;
public interface ReaderFactory {
Reader getReader();
}
④里面有一个getReader()方法返回我们的Reader来,为定义好的每个加载器都提供一个工厂类,这些工厂类实现了ReaderFactory
public class JpgReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new JpgReader();
}
}
public class PngReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new PngReader();
}
}
public class GifReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new GifReader();
}
}
- 为所有的产品先创建一个抽象类或者接口,然后通过实现抽象类或接口创建具体的产品类;
- 创建一个抽象的工厂类或者工厂接口,它里面有一个get方法,然后通过实现抽象的工厂类或工厂接口,针对每一种产品创建对应的工厂类;
- 使用时,通过创建产品对应的工厂类实例,调用get方法便可以获取具体的产品对象。
3、抽象工厂模式
抽象工厂模式:是工厂方法的进一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。
三、迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示;
迭代器模式把游走的任务放在迭代器上,而不是聚合上,这样简化了聚合的接口和实现,也可以让责任各得其所;
迭代器的构成与使用:
- 迭代器角色(Iterator):定义遍历元素所需要的方法,一般来说有三个方法:next() 方法取到当前的元素的方法并且移动到下一个元素的位置,hasNext() 方法:判断是否遍历结束,remove() 方法:移除当前对象;
- 具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代;
- 容器角色(Aggregate):一般是一个接口,提供一个iterator()方法,例如Java中的Collection接口,List接口,Set接口等;
- 具体容器角色(ConcreteAggregate):就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkedList,Set接口的哈希列表实现HashSet等;
使用方式: ①首先得有聚合对象; ②迭代器角色