山东省青州市建设局网站,wordpress 首页分页,yy直播间,ps做网站字号大小记录设计模式相关知识#xff0c;包括设计模式定义#xff0c;设计原则#xff08;单一职责#xff0c;开闭原则#xff0c;依赖倒置#xff0c;里式替换#xff0c;接口隔离#xff0c;迪米特原则#xff0c;组合聚合复用原则#xff09;#xff0c;单例模式#… 记录设计模式相关知识包括设计模式定义设计原则单一职责开闭原则依赖倒置里式替换接口隔离迪米特原则组合聚合复用原则单例模式原型模式并提供代码示例 文章目录 一、设计模式介绍二、设计原则三、设计模式单例模式原型模式 正文内容
一、设计模式介绍
设计模式是一种设计规范对于一类问题合理解决的思路与方式更高效解决一类问题对于编码来讲就是可以提高程序代码的可读性可扩展性复用性
可以提高程序员的思维能力编程能力和设计能力使程序更加标准化使软件开发效率大大提高使设计的代码可重用性高可读性强可靠性高灵活性好可维护性强更好的理解源码架构
通过设计模式帮助程序员构建更完善的系统编码编码过程中找到需求会发生变化的地方与不会发生变化的地方将两者分离开面向接口编程而不是面向实现编程实现高内聚低耦合
二、设计原则
单一职责 在设计的时候尽量让类或者方法只处理单一事件高内聚低耦合开闭原则 对扩展开放对修改关闭对于类或者方法进行功能增强是支持的对于类或者方法的修改关闭不在原有类或者方法上面进行修改为满足开闭原则一般使用抽象化设计里氏替换LSP 一个超类的对象应该能够被一个子类的对象替换而不影响程序的正确性 换句话说如果一个程序使用了基类那么它应该能够使用任何派生类的对象只要该派生类满足基类的行为期望。LSP确保子类可以替换其基类
代码示例如下
interface Shape {int area();
}class Rectangle implements Shape {private int width;private int height;public Rectangle(int width, int height) {this.width width;this.height height;}Overridepublic int area() {return width * height;}
}class Square extends Rectangle {public Square(int side) {super(side, side);}
}class AreaCalculator {public static int computeArea(Shape[] shapes) {int totalArea 0;for (Shape shape : shapes) {totalArea shape.area();}return totalArea;}
}public class Main {public static void main(String[] args) {Shape[] shapes new Shape[] {new Rectangle(2, 3),new Square(2),new Rectangle(3, 4),new Square(3)};System.out.println(AreaCalculator.computeArea(shapes));}
}在这个例子中我们有一个Shape接口其中有一个抽象方法area它将被子类重写。Rectangle类实现了area方法Square类继承了Rectangle类并重写了Square构造函数以保持宽度和高度相等创建了一个正方形。
AreaCalculator类的computeArea方法接受一个Shape对象数组并计算所有形状的总面积。此方法可以与任何类型的Shape对象包括Rectangle和Square一起使用而不必知道特定类型。这是因为Square类满足Shape类的预期行为可以代替Rectangle而不影响程序的正确性。
LSP是一个重要的原则因为它通过继承实现代码复用从而帮助创建灵活和易于维护的代码库。它还有助于防止错误并确保即使在代码发生更改时程序仍然可以正常工作。
依赖倒置 上层模块不应该依赖底层模块都应该依赖抽象抽象不依赖于细节细节应该依赖于抽象接口隔离 使用多个接口而不是使用单一的总接口不强迫新功能实现不需要的功能迪米特原则 一个对象对于其他对象有最少了解 比如说存在学院类学校类管理类管理类存在方法需要将学院信息学校信息进行输出此时根据迪米特原则分别将学员信息学校信息访问方法设计在学院类与学校类在管理类中调取这两个访问方法即可组合/聚合复用原则 模块A需要复用模块B时根据模块之间的关联程度尽量使用组合/聚合关系进行复用减小模块之间的耦合程度
三、设计模式
单例模式
单例模式类是一类事物共同属性行为的抽象具体到类中事物共同属性将会抽象成为类中的成员属性行为将会抽象成为类中的方法类中还包括构造器用于创建出一个具体的事物也就是Java中的对象通过构造器可以创建多个对象但是有的时候程序不需要多个对象对于这个类只需要创建一个对象时就需要使用单例模式
实现思路将构造器私有化外部无法创建对象但是此时需要该类对象所以需要提供外部方法供其他类访问该对象通过将类引用使用static修饰保证对象在整个程序运行期间的存在程序还需要保证对象的唯一性最简单不安全不建议的实现可以这样子
public class Singleton{private static Singleton singleton new Singleton();private Singlrton(){}public static Singleton getInstance(){return singleton;}
}上面代码在对象引用位置就创建对象就和饿汉看见食物之后很急切的开始吃食一样所以上述代码有很形象的名称饿汉式单例模式与之对应的还包括懒汉模式懒汉模式与饿汉模式最大的差别是两者创建对象的时期不一样懒汉式只有在对象第一次使用的时候创建将对象的创建时期推后需要考虑线程安全问题线程安全的懒汉式单例模式代码如下所示
public class Singleton {private static volatile Singleton singleton;private Singleton() {}public static Singleton getInstance() {if (singletonnull){synchronized (Singleton.class){if (singleton null) {singleton new Singleton();}}}return singleton;}
}在双重检锁单例模式中判断instance是否为null的原因是如果instance已经被实例化了那么就没有必要进入加锁的代码块直接返回已经实例化的instance即可。而第二次判断instance是否为null的原因是在多线程环境下可能存在多个线程同时通过了第一次判断进入了加锁的代码块但只有一个线程会获得锁实例化instance对象并将其赋值给instance变量。如果没有第二次判断那么其他线程在获得锁后也会再次实例化一个instance对象这就破坏了单例模式的原则因为这样就不再只有一个instance对象了。
在第二次判断中为了确保在多线程环境下instance变量的可见性和一致性通常会使用volatile关键字进行修饰。volatile关键字可以保证所有线程对instance变量的访问都是直接读写主存而不是读写线程私有的副本从而避免了可能的可见性和一致性问题。
原型模式
原型模式是一种创建型设计模式它允许通过克隆现有对象来创建新对象而不是通过实例化新的对象并赋值来创建新对象。原型模式主要涉及到两个角色即原型Prototype和具体原型Concrete Prototype。其中原型是一个抽象类或接口定义了一个 clone() 方法用于复制自身具体原型则是实现了原型接口的具体类它的 clone() 方法可以创建一个当前对象的副本。通过复制现有的对象原型模式可以避免在创建对象时昂贵的构造过程从而提高了创建对象的效率。
在使用原型模式时通常需要在程序中创建一个原型对象并将其存储在一个原型管理器Prototype Manager中。当需要创 建新对象时可以从原型管理器中获取一个原型对象然后通过克隆方法创建新对象。
以下是原型模式的基本结构 抽象原型Prototype定义一个克隆自身的接口方法。 具体原型Concrete Prototype实现抽象原型的克隆方法用于复制自身。 原型管理器Prototype Manager用于存储和管理原型对象。 原型模式的优点包括 可以避免创建对象时昂贵的构造过程从而提高创建对象的效率。 可以动态添加和删除原型对象。 可以实现深拷贝和浅拷贝以便灵活地复制对象。 原型模式的缺点包括 需要为每个类配备一个克隆方法这增加了代码量。 克隆方法对于含有循环引用或引用其他不可序列化的对象的复制会比较困难。 使用原型模式时需要注意深拷贝和浅拷贝的问题。
代码实现如下所示
public abstract class Shape implements Cloneable {private String id;protected String type;public String getId() {return id;}public void setId(String id) {this.id id;}public String getType() {return type;}public abstract void draw();Overridepublic Object clone() {Object clone null;try {clone super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return clone;}
}public class Rectangle extends Shape {public Rectangle() {type Rectangle;}Overridepublic void draw() {System.out.println(Inside Rectangle::draw() method.);}
}public class Square extends Shape {public Square() {type Square;}Overridepublic void draw() {System.out.println(Inside Square::draw() method.);}
}public class Circle extends Shape {public Circle() {type Circle;}Overridepublic void draw() {System.out.println(Inside Circle::draw() method.);}
}public class ShapeCache {private static MapString, Shape shapeMap new HashMap();public static Shape getShape(String shapeId) {Shape cachedShape shapeMap.get(shapeId);return (Shape) cachedShape.clone();}public static void loadCache() {Circle circle new Circle();circle.setId(1);shapeMap.put(circle.getId(), circle);Square square new Square();square.setId(2);shapeMap.put(square.getId(), square);Rectangle rectangle new Rectangle();rectangle.setId(3);shapeMap.put(rectangle.getId(), rectangle);}
}public class PrototypePatternDemo {public static void main(String[] args) {ShapeCache.loadCache();Shape clonedShape (Shape) ShapeCache.getShape(1);System.out.println(Shape : clonedShape.getType());Shape clonedShape2 (Shape) ShapeCache.getShape(2);System.out.println(Shape : clonedShape2.getType());Shape clonedShape3 (Shape) ShapeCache.getShape(3);System.out.println(Shape : clonedShape3.getType());}
}这里定义了一个抽象类Shape包含一个draw抽象方法和一个clone方法并有三个子类分别继承自Shape实现了draw方法。ShapeCache类用于缓存Shape对象其中使用getShape方法获取缓存的对象并使用clone方法进行复制。在PrototypePatternDemo类中通过缓存获取Shape对象并复制从而达到原型模式的效果。