目录
1、单例模式
1.1饿汉式--静态代码块
1.2饿汉式--静态常量
1.3懒汉式(线程不安全)【不可用】
1.4懒汉式(线程安全,同步方法)【不推荐使用】
1.5懒汉式(线程安全--同步代码块,双重检查)【推荐用】
1.6 静态内部类【推荐用】
2工厂方法模式
3 代理模式
4 观察者模式
5 适配器模式
单一职责原则
一个类只负责一个功能领域中的相应职责,原则是实现高内聚、低耦合。
开放封闭原则
一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
依赖倒置原则
抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
接口隔离原则
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
里氏代换原则
所有引用基类(父类)的地方必须能透明地使用其子类的对象。
迪米特法则
一个软件实体应当尽可能少地与其他实体发生相互作用
1、单例模式
单例模式
是在整个应用中保证只有一个类的实例存在。单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。
1.1饿汉式--静态代码块
public class Person {
//1.将构造函数私有化,外界无法通过new关键字创建对象
private Person() {
}
//2.该属性供静态方法getInstance使用,静态方法只能访问静态属性
// private static Person p = new Person();
private static Person p;
static {
p = new Person();
}
//3.提供一个方法给外界一个该类对象,使用static修饰以为外界无法创建对象,是通过调用该方法获取对象实例,所以该方法应该不用对象调用所以用static修饰名调用
public static Person getInstance() {
// return new Mother();//错误,调用一次方法就开辟一次空间违反单例
return p;
}
}
public class Test {
public static void main(String[] args) {
Person p = Person.getInstance();
Person p1 = Person.getInstance();
System.out.println(p);
System.out.println(p1);
System.out.println(p==p1);
// Person p3 = new Person();//报错
// System.out.println(p3);
}
}
这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。
1.2饿汉式--静态常量
public class Person {
//1.将构造函数私有化,外界无法通过new关键字创建对象
private Person() {
}
//2.该属性供静态方法getInstance使用,静态方法只能访问静态属性
// private static Person p = new Person();
private static Person p = new Person();;
// static {
// p = new Person();
// }
//3.提供一个方法给外界一个该类对象,使用static修饰以为外界无法创建对象,是通过调用该方法获取对象实例,所以该方法应该不用对象调用所以用static修饰名调用
public static Person getInstance() {
// return new Mother();//错误,调用一次方法就开辟一次空间违反单例
return p;
}
}
public class Test {
public static void main(String[] args) {
Person p = Person.getInstance();
Person p1 = Person.getInstance();
System.out.println(p);
System.out.println(p1);
System.out.println(p==p1);
// Person p3 = new Person();//报错
// System.out.println(p3);
}
}
优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
缺点:在类装载的时候就完成实例化,没有达到Lazy Loading(懒加载延迟加载)的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。
1.3懒汉式(线程不安全)【不可用】
//懒汉模式 单例
//懒汉式(线程安全,同步方法)【不推荐使用】 效率慢
public class Person extends Thread{
private Person() {
}
private static Person p;
public static synchronized Person getInstance() {
if (p==null) {
p = new Person();
}
return p;
}
}
优点:可以在使用是开辟空间,不使用不开辟空间。
缺点:线程不安全
这种写法起到了Lazy Loading的效果,但是只能在单线程下使用。如果在多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。
1.4懒汉式(线程安全,同步方法)【不推荐使用】
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {//同步类方法
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
解决上面第三种实现方式的线程不安全问题,做个线程同步就可以了,于是就对getInstance()方法进行了线程同步。
优点:懒汉式,用的时候开辟内存。线程安全。
缺点:效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低要改进。
1.5懒汉式(线程安全--同步代码块,双重检查)【推荐用】
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {//--------1 ,第二次第三次调用,不进入到同步代码块中
synchronized (Singleton.class) {
if (singleton == null) {//如果第一个线程执行到1cpu时间到,第二个线程可以全部将getInstance执行完。再回到线程1,此处如果不判断又开辟空间,违反单例
singleton = new Singleton();
}
}
}
return singleton;
}
}
Double-Check概念对于多线程开发者来说不会陌生,如代码中所示,我们进行了两次if (singleton == null)检查,这样就可以保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。
优点:线程安全;延迟加载;效率较高。
1.6 静态内部类【推荐用】
public class Singleton {
private Singleton() {}
private static class SingletonInstance {//私有静态内部类
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
优点:避免了线程不安全,延迟加载,效率高。
2工厂方法模式
一抽象产品类派生出多个具体产品类;一抽象工厂类派生出多个具体工厂类;每个具体工厂类只能创建一个具体产品类的实例。
定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类) 决定实例化哪一个类(具体产品类)。 “一对一”的关系。
public abstract class Fruit {
public abstract void getDesc();
}
public class Apple extends Fruit {
@Override
public void getDesc() {
// TODO Auto-generated method stub
System.out.println("我是苹果");
}
}
public class Pear extends Fruit {
@Override
public void getDesc() {
// TODO Auto-generated method stub
System.out.println("我是梨");
}
}
public abstract class FruitFactory {
public abstract Fruit product();
}
public class AppleFactory extends FruitFactory {
@Override
public Fruit product() {
// TODO Auto-generated method stub
return new Apple();
}
}
public class PearFactory extends FruitFactory {
@Override
public Fruit product() {
// TODO Auto-generated method stub
return new Pear();
}
}
//测试类
public class Entry {
public static void main(String[] args) {
PearFactory f= new PearFactory();
Fruit p = f.product();
p.getDesc();
}
}
3 代理模式
所谓代理
就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
举例:
生活中的例子:过年加班比较忙,没空去买火车票,这时可以打个电话到附近的票务中心,叫他们帮你买张回家的火车票,当然这会附加额外的劳务费。但要清楚票务中心自己并不卖票,只有火车站才真正卖票,票务中心卖给你的票其实是通过火车站实现的。这点很重要!
上面这个例子,你就是“客户”,票务中心就是“代理角色”,火车站是“真实角色”,卖票称为“抽象角色”!
Subject:抽象主题角色,抽象主题类可以是抽象类,也可以是接口,是一个最普通的业务类型定义,无特殊要求。
RealSubject:具体主题角色,也叫被委托角色、被代理角色。是业务逻辑的具体执行者。
Proxy:代理主题角色,也叫委托类、代理类。它把所有抽象主题类定义的方法给具体主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后工作。
public interface SellTicket {
public abstract void buyTicket();
}
public class Station implements SellTicket {
public String name;
public Station(String name) {
this.name = name;
}
@Override
public void buyTicket() {
// TODO Auto-generated method stub
System.out.println(name + "买票");
}
}
public class TicketCenter implements SellTicket {
public Station station;
public TicketCenter(Station station) {
this.station = station;
}
public void pay() {
System.out.println(station.name + "支付");
}
public void getTicket() {
System.out.println("取票");
}
@Override
public void buyTicket() {
// TODO Auto-generated method stub
pay();
station.buyTicket();
getTicket();
}
}
public class Client {
public static void main(String[] args) {
Station station = new Station("沈阳站点");
TicketCenter ticketCenter = new TicketCenter(station);
ticketCenter.buyTicket();
}
}
4 观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个方法,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。
//抽象观察者
public abstract class Person {
public abstract void action();
}
public class Student extends Person {
@Override
public void action() {
// TODO Auto-generated method stub
System.out.println("玩手机");
}
}
//具体观察者
public class Teacher extends Person {
@Override
public void action() {
// TODO Auto-generated method stub
System.out.println("走出教室");
}
}
import java.util.ArrayList;
public abstract class Subject {
//创建观察者对象的集合
ArrayList observers = new ArrayList();
public void addObserver(Person p) {
observers.add(p);
}
public void removeObserver(Person p) {
observers.remove(p);
}
//被final修饰的方法不能被覆盖 , 被final修饰的类不能被继承
public void notify1() {
for(Person p:observers) {
p.action();
}
}
}
//具体主题角色
public class Ring extends Subject {
public void classOver() {
notify1();
}
}
public class Entry {
public static void main(String[] args) {
// TODO Auto-generated method stub
Ring mRing = new Ring();
Student student= new Student();
Student student2 = new Student();
Teacher teacher = new Teacher();
mRing.addObserver(student);
mRing.addObserver(student2);
mRing.addObserver(teacher);
mRing.removeObserver(student);
mRing.classOver();
}
}
5 适配器模式
将一个接口转换成客户希望的另外一个接口。该模式使得原本不兼容的类可以一起工作
目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
需要适配的类(Adaptee):需要适配的类或适配者类。
适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
//目标接口
public class OldInterface {
public void oldMethod() {
System.out.println("oldMethod");
}
}
//需要适配的类
public class NewInterface {
public void newMothed() {
System.out.println("newMethod");
}
}
//目标接口
public class OldInterface {
public void oldMethod() {
System.out.println("oldMethod");
}
}
//适配器
public class Adapter extends OldInterface {
public NewInterface newInterface;
public Adapter(NewInterface newInterface) {
this.newInterface = newInterface;
}
@Override
public void oldMethod() {
// TODO Auto-generated method stub
newInterface.newMothed();
}
}
public class Entry {
public static void main(String[] args) {
NewInterface newInterface = new NewInterface();
OldInterface Adapter = new Adapter(newInterface);
Adapter.oldMethod();
}
}
1.学会了设计思想。
2.学会了一些简单的特效例子
好了这次的文章就到这了
如果觉得还不错的话,帮忙点个关注吧
希望能给博主点赞哎,评论臨,收藏良三连一波加粗样式



