Java设计模式_1(10/23)
目录单例模式
定义
确保类
只有一个
实例,而且自行实例化
并向整个系统提供这个实例。
- 一个类只有一个实例:构造方法一定不是Public公开的,即Private
- 构造出来的实例是类成员变量,即静态变量
- 再提供一个方法,用于外界访问这个实例
应用点:
-
序列号生成器、Web页面计数器
-
创建一个对象需要消耗很多资源,如:访问IO、数据库资源
饿汉式
public class SingletonPattern {
public static void main(String[] args){
}
}
class Singleton {
private static Singleton singleton = new Singleton(); // 饿汉式实现,使用这个对象的时候,立马就能够创建
private Singleton() {
}
public static Singleton getInstance() { // 仅此public公开
return singleton;
}
}
懒汉式
public class SingletonPattern {
public static void main(String[] args){
}
}
class Singleton {
private static Singleton singleton;
private Singleton() {
}
public synchronized static Singleton getInstance() { // 加锁,避免多次实例化
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
懒汉式(双重检查锁)
public class SingletonPattern {
public static void main(String[] args){
}
}
class Singleton {
private volatile static Singleton singleton; // volatile 保证线程可见性,保证线程安全
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) { // 如果singletone还没有初始化,这个时候用synchronized来同步加锁,再判断一次是否为空,来实例化对象
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
注:volatile
这个关键字的作用
-
Java语言提供了一种
稍弱
的同步机制
,即volatile变量,用来确保将变量的更新操作
通知到其他线程。当把变量声明为volatile类型后,编译器与运行时
都会注意到这个变量是共享
的,因此不会
将该变量上的操作与其他内存操作一起重排序
。volatile变量不会被缓存
在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入
的值。 -
在访问volatile变量时
不会执行加锁
操作,因此也就不会使执行线程阻塞
,因此volatile变量是一种比sychronized关键字更轻量级
的同步机制。 -
声明变量是 volatile 的,JVM 保证了每次读变量都
从内存
中读,跳过 CPU cache
这一步。
singleton = new Singleton()
可拆解为3步:分配内存、初始化对象、指向刚分配地址
-
若发生重排序,则先
指向刚分配地址
再初始化对象
这个时候就乱了。所以在双重检查锁的时候需要加上volatile修饰。 -
说白了就是在这里禁止重新排序。
单例模式最佳实现就是无状态的,不然这里调用一下赋值20,另一边调用赋值30,凡是用到这里的,都会因为改变而改变。
简单工厂模式
定义
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
简单工厂模式是用来创建某一大类下面不同类的实例的一种模式。
classDiagram Product <|.. ProductA Product <|.. ProductB ProductA <.. Factory:Use ProductB <.. Factory:Use class Product{ <<Abstract>> + method() } class ProductA{ + method() } class ProductB{ + methond() } class Factory{ + createProduct(string):Product }代码
public class SimpleFactory {
public static Product createProduct(String type) {
if (type.equals("A")) {
return new ProductA();
} else if (type.equals("B")) {
return new ProductB();
} else {
return null;
}
}
public static void main(String[] args) { // 调用方法
Product Product = SimpleFactory.createProduct("A");
Product.print();
}
}
abstract class Product { // 定义一个抽象类
public abstract void print();
}
class ProductA extends Product { // 负责具体的实现
@Override
public void print() {
System.out.println("ProductA");
}
}
class ProductB extends Product { // 负责具体的实现
@Override
public void print() {
System.out.println("ProductB");
}
}
优点
实现对象的创建和使用
分离,创建交给专门的工厂类负责,客户端程序员不关心怎么创建,只关心如何使用。
缺点
工厂类不够灵活
,如果要新增一个产品就需要修改工厂类,违反了开闭原则。
工厂模式
类似于把多个简单工厂给管理在一起,形成了一个大的工厂,并定义一个接口。
定义
classDiagram Factory <|.. FactoryAB Factory <|.. FactoryA Product <|.. ProductA Product <|.. ProductB ProductA <-- FactoryA:create ProductB <-- FactoryAB:create class ProductA { + method() } class ProductB { + method() } class FactoryAB { + createProduct(string): Product } class FactoryA { + createProduct(string): Product } class Product { <<Abstract>> + method() } class Factory { <<Abstract>> + createProduct(string): Product }定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
public calss FactoryPattern {
public static void main(String[] args) {
}
}
interface Phone {
void print();
}
class iPhone implements Phone {
@Override
public void print() {
System.out.println("iPhone");
}
}
class HuaWeiPhone implements Phone {
@Override
public void print() {
System.out.println("HuaWeiPhone");
}
}
interface Factory {
Phone createPhone();
}
class IPhoneFactory implements Factory {
@Override
public Phone createPhone() {
return new iPhone();
}
}
class HuaWeiPhoneFactory implements Factory {
@Override
public Phone createPhone() {
return new HuaWeiPhone();
}
}
抽象工厂模式
类似于把多个工厂给管理在一起,形成了一个大的工厂,并定义一个接口。
classDiagram Phone <|.. IPhone Phone <|.. HuaWei Factory <|.. FactoryA Factory <|.. FactoryB Mask <|.. N95 Mask <|.. KN90 FactoryB <-- HuaWei FactoryB <-- KN90 FactoryA <-- IPhone FactoryA <-- N95 class Phone { <<Abstract>> + method() } class IPhone { + method() } class HuaWei { + method() } class Mask { <<Abstract>> + method() } class N95 { + method() } class KN90 { + method() } class Factory { <<Abstract>> + createPhone(string): Phone + createMask(string): Mask } class FactoryB { + createPhone(string): Phone + createMask(string): Mask } class FactoryA { + createPhone(string): Phone + createMask(string): Mask }// 抽象工厂
interface AbstractFactory {
Phone createPhone(String param);
Mask createMask(String param);
}
// 具体工厂
class SuperFactory implements AbstractFactory {
@override
Phone createPhone(String param) {
return new iphone();
}
@Override
Mask createMask(String param) {
return new N95();
}
}
//产品大类 手机
interface Phone {}
class iPhone implements Phone {}
interface Mask {}
class N95 implements Mask {}
简单工厂xN = 工厂x1 => 工厂xN = 抽象工厂x1
装饰器模式
classDiagram Component <|.. ConcreateComponent Component <|.. Decorator Decorator <|.. ConcreateDecorator Decorator o-- Component class Component { + method() } class ConcreateComponent { + method() } class Decorator { + method() } class ConcreateDecorator { + method() }动态地给一个对象添加一些额外的功能。就增加功能来说,装饰器模式比生成子类更加灵活。
public class DecoratorPattern {
public static void main(String[] args) {
new RobotDecorator(new FirstRobot()).doMoreThing();
}
}
interface Robot {
void doSomething();
}
class FirstRobot implements Robot {
@Override
public void doSomething() {
System.out.println("对话");
System.out.println("唱歌");
}
}
class RobotDecorator implements Robot {
private Robot robot;
public RobotDecorator(Robot robot) {
this.robot = robot;
}
@Override
public void doSomething() {
robot.doSomething();
}
public void doMoreThing() {
robot.doSomething();
System.out.println("跳舞、拖地");
}
}
javaIO流也使用了装饰器模式
适配器模式
classDiagram Target <|.. Adapter Adapter o-- Adaptee class Target { <<Interface>> + request(): Type } class Adapter { + request(): Type } class Adaptee { +specificRequest(): Type } classDiagram Target <|.. Adapter Adaptee <-- Adapter: Extends class Target { <<Interface>> + request(): Type } class Adapter { + request(): Type } class Adaptee { +specificRequest(): Type }将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
适配器
突出适配,适配器模式会改变原有的实例方法,是改变
而不是新增。<会改变接口>
装饰器
模式不会改变原有的实例方法,只会新增
。<不会改变接口>
public class AdapterPattern {
public static void main(String[] args) {
new Adapter(new Speaker()).translate();
}
}
class Speaker {
public String speak() {
return "China No.1";
}
}
interface Translator {
public String translate();
}
class Adapter implements Translator {
private Speaker speaker;
public Adapter(Speaker speaker) {
this.speaker = speaker;
}
@Override
public String translate() {
String result = speaker.speak();
return null;
}
}
观察者模式
定义
classDiagram Debit <|.. ZhangSan Credit <|.. Wangwu Credit <|.. Zhaosi class Debit { <<Interface>> + borrow(Credit) + notifyCredits() } class ZhangSan { + borrow(Credit) + notifyCredits() } class Credit { <<Interface>> + takeMoney() } class Wangwu { + takeMoney() } class Zhaosi { + takeMoney() }观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变是,其相关依赖对象借的到通知并自动更新。
public class Observer Pattern {
public static void main(String[] args) {
Debit ZhangSan = new ZhangSan();
ZhangSan.borrow(new Wangwu());
ZhangSan.borrow(new Zhaosi());
//state change
ZhangSan.notifyCredits();
}
interface Debit {
void borrow(Credit credit);
void notifyCredits();
}
class ZhangSan implements Debit {
private List<Credit> allCredits = new ArrayList<>();
private Integer state = 0; // 1 表示有钱
@Override
public void borrow(Credit credit) {
allCredits.add(credit);
}
@Override
public void notifyCredits() {
allCredits.forEach(Credit -> Credit.takeMoney());
}
}
interface Credit {
void takeMoney();
}
class Wangwu implements Credit {
@Override
public void takeMoney() {
System.out.println("Wangwu take money");
}
}
class Zhaosi implements Credit {
@Override
public void takeMoney() {
System.out.println("Zhaosi take money");
}
}
外观模式
定义
说白了就隐藏内部细节,对外提供一个方法
classDiagram Facade <|.. SubSystemOne Facade <|.. SubSystemTwo Facade <|.. SubSystemThird class Facade { + methodA() + methodB() } class SubSystemOne { + methodOne() } class SubSystemTwo { + methodTwo() } class SubSystemThird { + methodthree() }要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。
外观模式提供一个高层次的接口,使得子系统更容易使用。
public class FacadePattern {
public static void main(String[] args) {
new Facade().prove();
}
}
class SubFlow1 {
boolean isTrue() {
return true;
}
}
class SubFlow2 {
boolean isOk() {
return true;
}
}
class SubFlow3 {
boolean isMan() {
return true;
}
}
class Facade {
SubFlow1 s1 = new SubFlow1();
SubFlow2 s2 = new SubFlow2();
SubFlow3 s3 = new SubFlow3();
boolean prove() {
return s1.isTrue() && s2.isOk() && s3.isMan();
}
}
缺点:违反了开闭原则
状态模式
定义
classDiagram Context o-- State State <-- Context State <|-- ConcreteStateA State <|-- ConcreteStateB class Context { +changeState(State *):void +request():void } class State { +handle():void } class ConcreteStateA { +handle():void } class ConcreteStateB { +handle():void }状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其类别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
public class StatePattern {
public static void main(String[] args) {
Context ZhangSan = new Context();
ZhangSan.changeState(new Happy());
ZhangSan.doSomething();
ZhangSan.changeState(new Sad());
ZhangSan.doSomething();
ZhangSan.changeState(new Angry());
ZhangSan.doSomething();
}
}
abstract class State {
abstract void doWork();
}
class Happy extends State {
@Override
void doWork() {
System.out.println("Happy");
}
}
class Angry extends State {
@Override
void doWork() {
System.out.println("Angry");
}
}
class Sad extends State {
@Override
void doWork() {
System.out.println("Sad");
}
}
class Context {
private State state;
public void changeState(State state) {
this.state = state;
}
public void doSomething() {
state.doWork();
}
}
优点:封装了转换规则,并枚举了可能的状态,它将所有与某个对状态有关的行为,放到了状态类中,并且可以方便地增加新的状态。还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:会增加系统(状态)类和(状态)对象的个数,使用不当会导致程序结构或代码的混乱。
策略模式
定义
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)
状态VS策略
状态强调的状态的不同,状态不同
,要做的事情不同
(开心->买肯德基犒劳犒劳自己,不开心->明天请假不上班),聚焦在开心或者不开心上,而开心或者不开心具体要做什么不关心,你不开心明天辞职也可以。
策略强调要做的事情不同
会导致做事情的具体步骤不同
,强调的是“做的步骤”
,即行为、算法本身。