单例模式
-
饿汉式单例
在类加载时就创建实例,简单方便,但是会多耗资源
public class Hunger { //类加载的时候就创建了实例 private static Hunger instance = new Hunger(); //私有构造方法,防止外部创建实例 private Hunger(){}; //对外提供获取实例的方法 public static Hunger getInstance(){ return instance; } }
-
懒汉式单例
只在需要实例时创建,第一次创建,之后获取唯一的实例。减少资源消耗,但是多线程时如果两个线程一前一后进入获取实例的逻辑,a线程进入逻辑但是还没有实例化时,b线程也同是进去就会破坏单例
/** * Created with IntelliJ IDEA. * * @Author:Grant * @Description:懒汉式创建,但是多线程会在判断实例为null后创建多个实例,a线程判断null后初始化实例同时b线程也判断了null,所以会创建多个实例 * @Date: 2024/06/17/14:42 */ public class Lazy { //创建实例但是不初始化 private static Lazy instance; //私有构造器 private Lazy() { } //获取实例 public static Lazy getInstance() { //只有实例不存在时创建 if (instance == null) { instance = new Lazy(); } return instance; } }
-
双重检查锁
通过锁住代码块并再次判断实例是否为空可以避免懒汉式的问题,通过volatile声明实例的可见性。
/** * Created with IntelliJ IDEA. * * @Author:Grant * @Description: * @Date: 2024/06/17/14:48 */ public class DoubleCheck { private static volatile DoubleCheck instance; private DoubleCheck() { } public static DoubleCheck getInstance() { if (instance == null) { synchronized (DoubleCheck.class) { if (instance == null) { instance = new DoubleCheck(); } } } return instance; } }
观察者模式
行为型模式,针对被观察者的变动,所有观察者都会检测到并作出对应动作。也叫订阅-发布模式。
优点:
1、通过接口进行解耦
2、可动态对观察者对象增加删减,灵活性提高
3、符合开闭原则
缺点:
1、观察者的增加删减需要小心,不当删除会导致内存泄漏
2、多个接口会复杂化程序
组成:
抽象被观察者:定义了一个接口,包含了注册观察者、删除观察者、通知观察者等方法。
具体被观察者:实现了抽象被观察者接口,维护了一个观察者列表,并在状态发生改变时通知所有注册的观察者。
抽象观察者:定义了一个接口,包含了更新状态的方法。
具体观察者:实现了抽象观察者接口,存储了需要观察的被观察者对象,并在被观察者状态发生改变时进行相应的处理。
一般来说被观察者会保存观察者的信息,通过观察者的接口完成事件的发布和对应的业务处理。
示例:
package com.grant.design.observer;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:生产者即被观察者
* @Date: 2024/06/19/14:24
*/
public interface Provider {
//添加观察者
void addConusmer(Consumer conusmer);
//移除观察者
void removeConusmer(Consumer conusmer);
//通知观察者
void notifyConusmer();
}
package com.grant.design.observer;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/06/19/14:25
*/
public interface Consumer {
void handle();
}
package com.grant.design.observer.impl;
import com.grant.design.observer.Consumer;
import com.grant.design.observer.Provider;
import java.util.ArrayList;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/06/19/14:26
*/
public class ProviderImpl implements Provider {
List<Consumer> consumers = new ArrayList<>();
@Override
public void addConusmer(Consumer conusmer) {
consumers.add(conusmer);
System.out.println("添加消费者,当前观察者数量:"+this.consumers.size());
}
@Override
public void removeConusmer(Consumer conusmer) {
consumers.remove(conusmer);
System.out.println("去除消费者,当前观察者数量:"+this.consumers.size());
}
@Override
public void notifyConusmer() {
consumers.forEach( item -> {
item.handle();
});
}
}
package com.grant.design.observer.impl;
import com.grant.design.observer.Consumer;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/06/19/14:34
*/
public class ConsumerImpl implements Consumer {
@Override
public void handle() {
System.out.println("消费者消费了");
}
}
package com.grant.design.observer.test;
import com.grant.design.observer.Provider;
import com.grant.design.observer.impl.ConsumerImpl;
import com.grant.design.observer.impl.ProviderImpl;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/06/19/14:37
*/
public class TestMain {
public static void main(String[] args) {
Provider provider = new ProviderImpl();
provider.addConusmer(new ConsumerImpl());
provider.notifyConusmer();
}
}
装饰器模式
简单来说装饰器模式就是有一个最基本的接口,基于这个接口对应的某个方面需要拓展的地方实现一个基本类,然后基于这个基本类可以拓展别的操作,如在原有的方法中需要做别的处理,类似于一个迭代链,在这个链中可以随意选取不同的装饰器组装,而且对原有的功能没有影响。
package com.grant.design.decorator.entity;
import lombok.Data;
import java.math.BigDecimal;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/16:16
*/
@Data
public class Obj1 {
private String id;
private BigDecimal price;
private Favorable favorable;
}
package com.grant.design.decorator.entity;
import lombok.Data;
import java.math.BigDecimal;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/16:19
*/
@Data
public class Favorable {
private int id;
private BigDecimal couponPrice;
}
package com.grant.design.decorator;
import com.grant.design.decorator.entity.Order;
import java.math.BigDecimal;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/16:20
*/
public interface OrderInterface {
public BigDecimal calculateOrderPrice(Order order);
}
package com.grant.design.decorator;
import com.grant.design.decorator.entity.Order;
import java.math.BigDecimal;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/16:29
*/
public class BaseOrder implements OrderInterface {
@Override
public BigDecimal calculateOrderPrice(Order order) {
return order.getPrice() - order.getFavorable().getCouponPrice;
}
}
package com.grant.design.decorator;
import com.grant.design.decorator.entity.Order;
import java.math.BigDecimal;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/16:31
*/
public abstract class BaseOrderDecorator implements OrderInterface {
private OrderInterface orderInterface;
public BaseOrderDecorator(OrderInterface orderInterface){
this.orderInterface = orderInterface;
}
@Override
public BigDecimal calculateOrderPrice(Order order) {
return orderInterface.calculateOrderPrice(order);
}
}
package com.grant.design.decorator;
import com.grant.design.decorator.entity.Order;
import java.math.BigDecimal;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/16:41
*/
public class FullReductionDecorator extends BaseOrderDecorator{
public FullReductionDecorator(OrderInterface orderInterface) {
super(orderInterface);
}
@Override
public BigDecimal calculateOrderPrice(Order order) {
order.setPrice(super.calculateOrderPrice(order));
return calculateFullReductionPrice(order);
}
private BigDecimal calculateFullReductionPrice(Order order){
return order.price.subtract(order.getFavorable().getCouponPrice);
}
}
//使用方式
OrderInterface orderInterface = new BaseOrder();
BaseOrderDecorator redPacketDecorator = new RedPacketDecorator(orderInterface);
BaseOrderDecorator fullReductionDecorator = new FullReductionDecorator(redPacketDecorator);
工厂模式
工厂模式,这里介绍简单工厂,方法工厂。工厂模式的使用时用于简化代码,减少重复的代码。
简单工厂
简单工厂提供了不需要知道具体类名的就可获取所需类的接口,简化了部分代码,但是可拓展性差,每当有新的类需要添加时就要对工厂类做修改,违反了开闭原则-对修改关闭,对拓展开放。
package com.grant.design.factory.SimpleFactory;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/06/19/14:57
*/
public class SimpleFactory {
public static Father getObject(String type)
{
switch (type){
case "son1":
return new Son1();
case "son2":
return new Son2();
default:
return null;
}
}
}
这就是一个简单工厂的例子,对于工厂类来说,通过基类和参数可以返回不同类,使用者也不需要知道具体类名。
方法工厂
区别于简单工厂的拓展性差,产品种类少的缺点,方法工厂在原有的工厂类上又抽象出一个工厂接口,可自行选择不同的工厂类,再将具体的实例获取推迟到各个子工厂中。这种方式耦合性低,拓展性强,针对复杂产品可有条理的解决。
//三个基类
package com.grant.design.factory.methodFactory;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/15:27
*/
@Data
public class Product {
private String name;
private Long id;
}
package com.grant.design.factory.methodFactory;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/15:28
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product1 extends Product{
private String name = "Product1";
private String description;
}
package com.grant.design.factory.methodFactory;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/15:28
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product2 extends Product{
private String name = "Product2";
private String date;
}
package com.grant.design.factory.methodFactory;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/06/19/15:20
*/
public interface AbstractFactory {
Product getObject();
}
package com.grant.design.factory.methodFactory;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/15:25
*/
public class Product1Factory implements AbstractFactory{
@Override
public Product getObject() {
return new Product1();
}
}
package com.grant.design.factory.methodFactory;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/15:25
*/
public class Product2Factory implements AbstractFactory{
@Override
public Product getObject() {
return new Product2();
}
}
package com.grant.design.factory.methodFactory;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/01/15:34
*/
@Data
@AllArgsConstructor
public class ClientStore {
private AbstractFactory factory;
public void setFactory(AbstractFactory factory) {
this.factory = factory;
}
public void getProduct() {
Product product = factory.getObject();
System.out.println(product.getName());
}
}
package com.grant.design.factory;
import com.grant.design.factory.SimpleFactory.Father;
import com.grant.design.factory.SimpleFactory.SimpleFactory;
import com.grant.design.factory.methodFactory.ClientStore;
import com.grant.design.factory.methodFactory.Product1Factory;
import com.grant.design.factory.methodFactory.Product2Factory;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/06/19/15:02
*/
public class TestMain {
public static void main(String[] args) {
//methodFactory
ClientStore clientStore = new ClientStore(new Product1Factory());
clientStore.getProduct();
clientStore.setFactory(new Product2Factory());
clientStore.getProduct();
}
}
建造者模式
当一个类在构造时有很多的参数并且这些参数都是可选时就可以使用建造者模式。
通过在类内部构造静态builder类并在其中构造源类的实例返回。静态类中的参数需要和源类一致。
package com.grant.design.builder;
import lombok.Data;
import lombok.ToString;
/**
* Created with IntelliJ IDEA.
*
* @Author:Grant
* @Description:
* @Date: 2024/07/02/11:23
*/
@Data
@ToString
public class Product {
String id;
String name;
String description;
public Product(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.description = builder.description;
}
public static class Builder {
String id;
String name;
String description;
public Builder setId(String id) {
this.id = id;
return this;
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setDescription(String description) {
this.description = description;
return this;
}
public Product build() {
return new Product(this);
}
}
}