1、单例模式
定义:它是java所有设计模式中最简单的一种,它提供了一个创建对象的最佳方法,
那些地方用到了单例模式?
1、网站计数器,一般采用单例模式,否则难以同步 2、应用程序的日志应用一般采用单例模式 3、多线程的线程池一般也是采用单例模式 4、windows中的任务管理器是典型的单例模式,不可以开启两个 5、windows中的回收站也是单例模式
单例模式的创建?
主要是懒汉式和饿汉式 1、饿汉式:类初始化的时候会立刻加载该对象,天生的线程安全,调用效率高。
饿汉式实现的步骤: 1、构造器私有化. 2、类的内部创建一个对象的实例。 3、向外提供一个静态的方法用来获取对象的实例。
优点:在类加载的过程中就创建的实例,避免的线程同步的问题(线程的聚绝对安全)。 缺点:如果从开始的时候就没有使用这个实例,就造成的内存的浪费。
class Singleton{
private Singleton(){
}
private final static Singleton instance =new Singleton();
public static Singleton getInstance(){
return instance;
}
}
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance==instance1);
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
true
1956725890
1956725890
2、懒汉式:类初始化的时候,不会初始化该对象,真正使用的时候才会创建该对象,具有懒加载的功能。
实现步骤: 1、私有化构造器 2、向外提供一个静态的方法,用来获取对象的实例。
优点:实现了懒加载的效果,但是只能在单线程的情况下使用。 缺点:如果两个线程同时进入了if条件语句,那么就会创建多个实例(线线程不安全)
class Singleton{
private Singleton(){
}
private static Singleton instance;
public static Singleton getInstance(){
if(instance ==null){
instance = new Singleton();
}
return instance;
}
}
public static void main(String[] args) {
System.out.println("这是懒汉式,线程不安全");
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance==instance1);
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
这是懒汉式,线程不安全
true
1956725890
1956725890
3、内部静态类的方法:结合了懒汉式和饿汉式的各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。
class Singleton {
private static volatile Singleton instance;
private Singleton() {
}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static synchronized Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
4、枚举单例:使用枚举实现单例模式,实现简单,调用率高,枚举的本身就是一个单例模式,由JVM从根本上提供保障。
2、工厂模式?
1、它提供了一种创建对象的最佳方式。 2、在工厂模式中通过使用一个共同的接口来指向新创建的对象。实现了创建者和调用者分离。 工厂模式分为简单工厂、工厂方法、抽象工厂模式 简单工厂 :用来生产同一等级结构中的任意产品。 工厂方法 :用来生产同一等级结构中的固定产品。 抽象工厂 :用来生产不同产品族的全部产品。
优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则
具体示例:
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
public class ShapeFactory {
public Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
shapeType = shapeType.toLowerCase();
switch (shapeType) {
case "circle":
return new Circle();
case "rectangle":
return new Rectangle();
case "square":
return new Square();
default:
return null;
}
}
}
1、代理模式
1.1静态代理
- 静态代理:由程序员创建,也就是在编译时就将接口、被代理类、代理类等确定下来,在程序运行之前,代理类.class文件以及生成。
- 它主要就是有一个公共的接口、一个被代理类,以及一个代理类,这两个类都实现了这个接口,这个公共的接口定义了被代理类的一个行为规范,代理类持有被代理类的具体实现方法,而且代理类还可以在执行被代理类的方法之前添加额外的行为,这就是代理模式的一个很大的优点,体现最直白的地方就是SpringAOP(面向切面编程),我们可以在切点之前和之后都添加一些操作,而这些切点就是一些方法,而这些方法所在的类就是被代理的,这也是面向编程的主要思想。
- 示例:
public interface Person {
void giveMoney();
}
public class Student implements Person {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void giveMoney() {
System.out.println(name + "上交班费50元");
}
}
public class StudentsProxy implements Person{
Student stu;
public StudentsProxy(Person stu) {
if(stu.getClass() == Student.class) {
this.stu = (Student)stu;
}
}
public void giveMoney() {
stu.giveMoney();
}
}
public class StaticProxyTest {
public static void main(String[] args) {
Person zhangsan = new Student("张三");
Person monitor = new StudentsProxy(zhangsan);
monitor.giveMoney();
}
}
1.2动态代理
3、观察者模式
- 对象之间存在着一对多的关系,那就使用观察者模式,比如当一个对象被修改的时候,可以自动通知它依赖的对象做出相对应的更新修改。
- 一般来说观察者模式主要有三各类,Subject(主题类),Observe抽象类(观察类),Cilent(客户端),Subject类主要实现存储观察者的一个ArrayList,将观察者添加到观察列表中的方法attach(),以及通知所有观察者的方法notifyAllObserve()方法。以及状态的修改方法setStatue()。
- 示例:
public class Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Binary String: "
+ Integer.toBinaryString(subject.getState()));
}
}
public class OctalObserver extends Observer {
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: "
+ Integer.toOctalString( subject.getState() ) );
}
}
public class HexaObserver extends Observer {
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Hex String: "
+ Integer.toHexString( subject.getState() ).toUpperCase() );
}
}
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new BinaryObserver(subject);
new HexaObserver(subject);
new OctalObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println();
System.out.println("Second state change: 10");
subject.setState(10);
}
}
First state change: 15
Binary String: 1111
Hex String: F
Octal String: 17
Second state change: 10
Binary String: 1010
Hex String: A
Octal String: 12
|