一、单例模式
为什么使用单例模式呢,那就需要理解我们什么时候会使用到单例。
比如有些对象我们只需要一个,例如配置文件、工具类、线程池、缓存、日志等,,,,
这个时候我们就会需要一个单例,而不需要在使用的时候创建了其他的实例。
单例模式分为 饿汉模式 懒汉模式
那么接下来用代码来看看单例模式的实现吧
饿汉模式的单例(线程安全的)
package com.Singleton;
/** * 单例模式 应用场合:有些对象只需要一个就足够了,如古代皇帝 作用: * 保证整个应用程序中某个实例只有一个 类型:饿汉模式 懒汉模式 * * @author ruolan * */
public class Singleton {
// 饿汉模式 在类加载的时候,就会创建类的唯一的实例
// 1、构造方法私有化,不允许外部直接创建对象
private Singleton() {
}
// 2、创建类的唯一实例(私有的,不允许外部成员访问)
private static Singleton instance = new Singleton();
// 3、提供一个用于获取实例的公开的静态的方法
// static 在类加载的时候直接加载。
public static Singleton getInstance() {
return instance;
}
}
测试类:
package com.Singleton;
public class Test {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
if (s1 == s2) {
System.out.println("s1和s2是同一个实例");
} else {
System.out.println("s1和s2不是同一个实例");
}
}
}
输出结果
s1和s2是同一个实例
懒汉模式:
package com.Singleton;
//懒汉模式
//
public class Singleton2 {
// 1、将构造方法私有化
private Singleton2() {
}
// 2、声明这个类的唯一实例,使用private static修饰
private static Singleton2 instance;
// 3、提供一个公开的静态的方法获取实例
public static Singleton2 getInstance() {
if (instance == null) {
//代码改成这样之后,只有在instance还没被初始化的时候才会进入到第3行,然后加上同步锁。
//等instance一但初始化完成了,就再也走不到第3行了,这样执行getInstance方法也不会再
//受到同步锁的影响,效率上会有一定的提升。
synchronized (Singleton2.class) {
if (instance == null) {
instance = new Singleton2();
}
}
}
return instance;
}
}
测试类:
package com.Singleton;
public class Test {
public static void main(String[] args) {
Singleton2 s3 = Singleton2.getInstance();
Singleton2 s4 = Singleton2.getInstance();
if (s3 == s4) {
System.out.println("s3和s4是同一个实例");
} else {
System.out.println("s3和s4不是同一个实例");
}
}
}
输出结果:
s3和s4是同一个实例
那么懒汉模式和饿汉模式的区别呢?
区别:饿汉模式在加载类的时候比较慢,运行的时候获取对象的速度快(已经创建了)线程安全
懒汉模式在加载类的时候比较快,运行的时候获取对象的速度慢(还没创建)线程不安全这个时候就要加锁了。
二、工厂模式
1、工厂模式的概念
实例化对象,用工厂方法代替new操作
2、什么情况下使用工厂模式
有一组类似的对象要创建
在编码的时候不能预测要创建那种类的实例
系统需要考虑扩展性,不应该依赖于产品类实例被创建、组合和表达的细节
3、工厂模式的uml图
下面我们就来利用一个实例来简单的实现一下工厂模式吧
package com.sunny.project;
/** * 发型接口 * @author ruolan * */
public interface HairInterface {
//实现了发型
public void draw();
}
package com.sunny.project;
/** * 发型工厂 * * @author ruolan * */
public class HairFactory {
/** * 根据类型来创建对象 * * @param key * @return */
public HairInterface getHair(String key) {
if ("left".equals(key)) {
return new LeftHair();
} else if ("right".equals(key)) {
return new RightHair();
}
return null;
}
/** * 根据类的名称来生产对象 * @param className * @return */
public HairInterface getHairByClass(String className){
try {
HairInterface hair = (HairInterface) Class.forName(className).newInstance();
return hair;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
package com.sunny.project;
/** * 画一个左偏分发型 * @author ruolan * */
public class LeftHair implements HairInterface {
@Override
public void draw() {
System.out.println("---左偏分发型----");
}
}
package com.sunny.project;
public class RightHair implements HairInterface{
@Override
public void draw() {
System.out.println("----右偏分发型----");
}
}
测试类:
package com.sunny.project;
public class SunnyTest {
public static void main(String[] args) {
HairFactory factory = new HairFactory();
HairInterface left = factory.getHair("left");
if (left != null) {
left.draw();
}
}
}
输出结果:
---左偏分发型----
抽象工厂模式
1、抽象工厂模式uml图
2、来看下具体的实现吧
先创建一个uml图形中的Factory——>PersonFactory
package com.sunny.project;
public interface PersonFactory {
//男孩接口
public Boy getBoy();
//女孩接口
public Girl getGirl();
}
这里创建一个uml中ConcreteFactory1的—–> MCFactory
package com.sunny.project;
public class MCFactory implements PersonFactory{
@Override
public Boy getBoy() {
return new MCBoy();
}
@Override
public Girl getGirl() {
return new MCGirl();
}
}
这里创建一个uml中ConcreteFactory2的—–> XNFactory
package com.sunny.project;
public class XNFactory implements PersonFactory{
@Override
public Boy getBoy() {
return new XNBoy();
}
@Override
public Girl getGirl() {
return new XNGirl();
}
}
这里创建一个uml中AbstractProductA的—–> Boy
package com.sunny.project;
public interface Boy {
public void drawBoy();
}
这里创建一个uml中AbstractProductB的—–> Girl
package com.sunny.project;
public interface Girl {
public void drawWoman();
}
这里创建一个uml中ConcreteProducrA1的—–> MCBoy
package com.sunny.project;
public class MCBoy implements Boy {
@Override
public void drawBoy() {
System.out.println("圣诞系列的男孩");
}
}
这里创建一个uml中ConcreteProducrA1的—–> MCGirl
package com.sunny.project;
public class MCGirl implements Girl {
@Override
public void drawWoman() {
System.out.println("圣诞系列的女孩");
}
}
这里创建一个uml中ConcreteProducrB的—–> XNGirl
package com.sunny.project;
public class XNGirl implements Girl {
@Override
public void drawWoman() {
System.out.println("新年系列的女孩");
}
}
这里创建一个uml中ConcreteProducrB的—–> XNBoy
package com.sunny.project;
public class XNBoy implements Boy {
@Override
public void drawBoy() {
System.out.println("新年系列的男孩");
}
}
测试类:
package com.sunny.project;
public class SunnyTest {
public static void main(String[] args) {
PersonFactory factory = new MCFactory();
Girl girl = factory.getGirl();
girl.drawWoman();
Boy boy = factory.getBoy();
boy.drawBoy();
}
}
运行结果:
圣诞系列的女孩
圣诞系列的男孩
工厂模式的实现帮助我们:
系统可以在不修改具体工厂角色的情况下引进新的产品
客户端不必关心对象如果创建,明确了职责
更好的理解面向对象的原则,面向接口编程,而不要面向实现编程
工厂方法模式和抽象工厂模式对比:
工厂模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成工厂模式的推广
工厂模式用来创建一个产品的等级结构,而抽象工厂模式是用来创建多个产品的等级结构
工厂模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类
工厂模式使用的哪些场景:
一个系统应当不依赖于产品类实例被创立、组成、和表示的细节,这对于所有形态的工厂模式都是重要的
这个系统的产品有至少一个产品族
同属于一个产品族的产品是设计成在一起使用的,这一约束必须的在系统的设计中体现出来
不同的产品以一种接口的面貌出现,从而使系统不依赖于接口实现的细节
三、观察者模式
下面我们来看下定义吧:
1. 概述
有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
解决的问题
将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。
模式中的角色
3.1 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
3.2 具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
3.3 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
3.4 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
4.观察者模式结构:
5.准备阶段
6.运行阶段
下面我们就用一个例子来看下吧:
Observer类 ——–> Observer
package WeatherObserverPattern;
/** * 观察者接口,定义一个更新的接口给那些目标发生改变的时候 * 被通知的对象 * @author ruolan * */
public interface Observer {
//观察者进行更新的接口
//传入目标对象,方便获取相应的目标对象
public void update(WeatherSubject subject);
}
ConCreateObserver类 ——–>ConreateObserver
package WeatherObserverPattern;
/** * 具体的观察者对象,实现更新的方法, 使自身的状态和目标的状态保持一致 * * @author ruolan * @param <ConcreteSubject> * */
public class ConreateObserver implements Observer {
//观察的名字,是谁收到了信息,黄明的女票还是老妈
private String obserberName;
//天气的内容的情况,这个消息从目标出获取
private String weatherContent;
//提醒的内容:黄明的女票提醒约会,黄明的老妈提醒购物
private String remindThing;
public String getObserberName() {
return obserberName;
}
public void setObserberName(String obserberName) {
this.obserberName = obserberName;
}
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
}
public String getRemindThing() {
return remindThing;
}
public void setRemindThing(String remindThing) {
this.remindThing = remindThing;
}
// 观察者状态
private String weatherState;
/** * 获取目标类的状态,同步到观察者的状态中 */
@Override
public void update(WeatherSubject subject) {
//获取天气内容
weatherState = ((WeatherConcreteSubject) subject).getWeatherState();
System.out.println(obserberName + "收到了" + weatherState + "," + remindThing);
}
/** * 所需变量 : 1、观察者的名字 2、天气情况的内容 3、提醒的内容 */
}
Subject类 ——–>WeatherSubject
package WeatherObserverPattern;
import java.util.ArrayList;
import java.util.List;
/** * 目标对象,他知道观察他的观察者额 并提供注册添加和删除观察者的接口 * * @author ruolan */
public class WeatherSubject {
// 用一个集合来保存注册的观察者对象
private List<Observer> observers = new ArrayList<>();
// 把观察者添加集合
public void attach(Observer observer) {
observers.add(observer);
}
//删除集合中的指定订阅天气的
public void detach(Observer observer){
observers.remove(observer);
}
//通知所有已经订阅了天气的人,只能子类调用
protected void notifyObservers(){
for (Observer observer : observers) {
observer.update(this);
}
}
}
ConcreteSubject类 ——> WeatherConcreteSubject
package WeatherObserverPattern;
/** * 具体的目标对象,负责把有关状态存入到相应的观察者对象中 * @author ruolan * */
public class WeatherConcreteSubject extends WeatherSubject {
private String weatherState;
public String getWeatherState() {
return weatherState;
}
public void setWeatherState(String subjectState) {
this.weatherState = subjectState;
this.notifyObservers();//状态发生改变就通知观察者
}
}
Client类
package WeatherObserverPattern;
public class Client {
public static void main(String[] args) {
//1、创建一个目标
WeatherConcreteSubject weather = new WeatherConcreteSubject();
//2、创建观察者
ConreateObserver observerGirl = new ConreateObserver();
observerGirl.setObserberName("黄明的女票");
observerGirl.setRemindThing("是我们的第一次约会,地点是天桥,不见不散");
ConreateObserver observerMum = new ConreateObserver();
observerMum.setObserberName("黄明的妈妈");
observerMum.setRemindThing("是一个购物的好日子,明天去购物去吧");
//3、注册观察者
weather.attach(observerGirl);
weather.attach(observerMum);
//4、目标发布天气
weather.setWeatherState("明天天气晴朗,蓝天白云,气温28度");
}
}
运行结果:
黄明的女票收到了明天天气晴朗,蓝天白云,气温28度,是我们的第一次约会,地点是天桥,不见不散
黄明的妈妈收到了明天天气晴朗,蓝天白云,气温28度,是一个购物的好日子,明天去购物去吧
在这里感谢一下慕课网的老师哈,今天就到这了,明天继续。。。。。。