程序:1.可维护性、2.可复用性、3.可扩展性、4.灵活性好 ;通过封装、继承、多态把程序的耦合度降低
开放-封闭原则(设计总原则)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等
单一职责原则
就一个类而言,应该仅有一个引起它变化的原因(如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多一个的职责,就应该考虑类的职责分离)
依赖倒转原则
抽象不应该依赖细节,细节应该依赖于抽象;高层模块不应该依赖低层模块。两个都应该依赖抽象
里氏代换原则
子类型必须能够替换它们的父类型。 只有当子类可以替换掉父类,在软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。正是因为子类的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展。 如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的射击,反之那就是过程化的设计。
迪米特原则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
合成/聚合复用原则
如果新对象的某些功能在别的已经创建好的对象里面已经实现,那么尽量使用别的对象提供的功能,使之成为新对象的一部分,而不要自己再重新创建。新对象通过向这些对象的委派达到复用已有功能的。 简而言之,要尽量使用合成/聚合,尽量不要使用继承。
接口隔离原则
不需要将所有的东西都放在一个接口里面,应该是定义多个功能专一的接口。过于臃肿的接口只会强迫客户依赖于不需要的方法。
设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
单例模式(singleton)—单线程
保证一个类仅有一个实例,并提供一个访问它的全局访问点,避免一个全局使用的类频繁的创建和销毁,节省系统资源,提高程序效率。Java是这么创建实例的 Person p = new Person();但是这么创建会创建多个实例,所以我们必须把构造器(构造方法)设为私有(private),这样其他类就不能使用new来实例化一个类。所有类都有构造方法,不编码则系统默认生成空的构造方法,若有显示定义的构造方法,则默认的构造方法就会失效。
“通常我们可以让一个全局变量使得一个对象被访问,但他不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个可以保证没有其它实例可以被创建,并且它可以提供一个访问该实例的方法。”
Singleton 类,定义一个GetInstance 操作,允许客户访问它的唯一实例。GetInstance 是一个静态方法,主要负责创建自己的唯一实例。
package singleton;
public class Singleton {
//定义一个属性,用来保存Singleton类对象的实例
private static Singleton instance;
//构造方法让其private,这样就可以堵死外界利用new创建此类实例的可能
private Singleton() {
}
//此方法是获得本类实例的唯一全局访问点
public static Singleton GetInstance() {
//若实例不存在,则new一个新实例,否则返回已有的实例
if (instance == null) {
instance = new Singleton();
}
return instance; //若实例存在,直接返回实例对象
}
}
客户端代码
package singleton;
import java.io.Console;
public class Main {
public static void main(String[] args) {
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
//比较两次实例化后对象的结果是实例相同
System.out.println(s1 == s2); //结果为true---->表示为同一个实例对象
}
}
这种实现方式并不是线程安全的,当有多个线程同时调用Singleton.getInstance()方法时会产生多个实例。需要通过改造,在多线下如何实现单例模式。可以给进程一把锁来处理,确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程视图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
package singleton;
public class Singleton {
//定义一个属性,用来保存Singleton类对象的实例
private static Singleton instance;
//构造方法让其private,这样就可以堵死外界利用new创建此类实例的可能
private Singleton() {
}
//此方法是获得本类实例的唯一全局访问点
public static Singleton GetInstance() {
//先判断实力是否存在,不存在再加锁处理
//synchronized加锁同步会降低效率,这里先判断是否为空
//不为空则不需要加锁,提高程序效率
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance; //若实例存在,直接返回实例对象
}
}
现在这样,我们不用让线程每次都加锁,而只是在实例未被创建的时候再加锁处理。同时也能保证多线程的安全。这种做法被称为双重锁定。
package cn.smbms.tools;
public class Singleton {
private static Singleton singleton;
private Singleton(){
//在整个应用运行期间,只执行一次的业务代码操作(比如:读取配置文件的操作)
}
public static class SingletonHelper{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHelper.INSTANCE;
}
public static Singleton test(){
return singleton;
}
}
客户端代码
package cn.smbms.tools;
public class TestSingleton {
public static void main(String[] args) {
System.out.println("Singleton.test()-----> "
+ Singleton.test());
System.out.println("Singleton.getInstance()-----> "
+ Singleton.getInstance());
}
}
测试结果
在静态初始化的方式是在自己被加载时就将自己实例化,所以被形象的称之为饿汉式单例类(缺点是,会提前占用系统资源)。而在第一次被引用时,才会将自己实例化,被称之为懒汉式单例类(缺点是,面临多线程访问的安全性问题,及非线程安全模式类)。
单例模式优点
1 在内存中只有一个对象,节省内存空间。
2 避免频繁的创建销毁对象,可以提高性能。
3 避免对共享资源的多重占用。
4 可以全局访问。
适用场景
1 需要频繁实例化然后销毁的对象。
2 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3 有状态的工具类对象。
4 频繁访问数据库或文件的对象。
5 以及其他所有要求只有一个对象的场景。
单例模式的更多方法应用参考:https://blog.csdn.net/qq_35400008/article/details/80569093