面向对象
面向对象编程(OOP,Object Oriented Programming)、面向对象分析(OOA)、面向对象设计(OOD)
例子:有一天我想要买一台电脑:1、从网上购买电脑的各种零件:主板、CPU、硬盘、显示器、外设等,然后进行组装。2、直接从网上买一台组装好的电脑。对于第一种就是面向过程,第二种是面向对象。面向对象有什么优势,首先我不需要知道组装电脑需要哪些零件和组装的流程,降低了耦合度,如果我突然不想买电脑了想要买手机,我只需要从网上买手机就好,提高了可维护性。面向对象降低耦合,提高维护性。面向过程是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现;面向对象是模型化的,你只需要抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,我们不用管,只需要知道输入和输出就可以。面向对象的底层还是面向对称,把面向过程抽象成类,然后封装,方便我们使用的就是面向对象。
面向过程:优点:性能比面向对象好,因为类调用时需要实例化,开销比较大,比较消耗资源。缺点:不易维护、不易复用、不易扩展。
面向对象:优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护。缺点:性能比面向过程差。
面向对象三个特性:封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。继承:提高代码复用性;继承是多态的前提。多态:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
面向对象五个基本原则:单一职责原则:类的功能要单一,不能包罗万象,跟杂货铺似的。开放封闭原则:一个模块对于拓展是开放的,对于修改是封闭的,只能扩展而不能修改。里氏替换原则:子类可以替换父类出现在父类能够出现的任何地方。例:你代替你爸爸在家里干活。依赖倒置原则:高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。例:出国后,你说自己是中国人,而不能说你是哪个村子的。中国是抽象,下面具体有省份、县市等,你要依赖的是抽象的中国,而不是下面的村,别人不认识。接口分离原则:设计时采用多个与特定客户类有关的接口要比采用一个通用的接口要好。例:一个手机有打电话、看视频、玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。
注:1、抽象会使复杂的问题更加简单化;2、从以前的面向过程的执行者,变成了面向对象的指挥官;3、面向对象更符合人类的思维,面向过程则是机器的思想。
单例模式
懒汉式(不可用)
public class LazySingleton {
public static LazySingleton instance = null;
private LazySingleton(){}
public static LazySingleton getInstance(){
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
private void show(){
System.out.println("LazySingleton");
}
}
描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。
优点:比较懒,在类加载时,不创建实例,所以类加载速度快。
缺点:运行时获取对象的速度慢,不能保证线程安全。
懒汉式(线程安全)(可用)
public class LazySingleton {
public static LazySingleton instance = null;
private LazySingleton(){}
public static synchronized LazySingleton getInstance(){
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
private void show(){
System.out.println("synchronized LazySingleton");
}
}
描述:这种方式具备了很好的懒加载,能够在多线程中很好的工作。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁synchronized才能保证单例,但加锁会影响效率。
饿汉式(可用)
public class HurrySingleton {
public static HurrySingleton instance = new HurrySingleton();
private HurrySingletonn(){}
public static HurrySingleton getinstance(){
return instance;
}
private void show(){
System.out.println("HurrySingleton");
}
}
描述:比较常见的写法,在类加载的时候就完成了实例化,避免了多线程的同步问题。
优点:没有加锁,执行效率会很高。
缺点:类加载就初始化,浪费内存。
双检索懒汉式(可用,推荐)
public class DLockSingleton {
private volatile static DLockSingleton instance = null;
private DLockSingleton(){}
public static DLockSingleton getInstance(){
if(instance == null){
synchronized (DLockSingleton.class){
if(instance == null){
instance = new DLockSingleton();
}}}
return instance;
}
private void show(){
System.out.println("Double-checked Locking");
}
}
描述:使用了两个if判断,并且同步的不是方法,而是代码块,效率较高。为什么做两次判断?这是为了线程安全考虑,对象还没实例化,两个线程A和B同时访问静态方法并同时运行到第一个if判断语句,这是线程A先进入同步代码块中实例化对象,结束之后线程B也进入同步代码块,如果没有第二个if判断语句,那么线程B也同样会执行实例化对象的操作。
优点:采用双锁机制,安全且在多线程情况下能保持高性能。
缺点:实现较复杂。