栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java设计模式原则

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java设计模式原则

目录

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.学会了一些简单的特效例子

好了这次的文章就到这了
如果觉得还不错的话,帮忙点个关注吧
希望能给博主点赞哎,评论臨,收藏良三连一波加粗样式


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1024625.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号