在这里插入图片描述
单例对象能节约系统资源,一个对象的创建和消亡的开销可能很小。但是日常的服务接口,就算是一般小公司也有十几万的QPS吧。每一次的功能运转都创建新的对象来响应请求,十几万对象的创建和销毁,想想就是一笔大开销,所以 spring 管理构造的 bean 对象一般都是单例。而且单例模式可以更好的解决并发的问题,方便实现数据的同步性
//饿汉式
private static Singleton singleton = new Singleton();
//懒汉式
private static Singleton singleton;
public static Singleton getSingleton(){
if (singleton == null) {
singleton = new Singleton(); //被动创建,在真正需要使用时才去创建
}
return singleton;
}
//双重判断加锁机制
private volatile static Singleton instance;
//程序运行时创建一个静态只读的进程辅助对象
public static Singleton GetInstance() {
//先判断是否存在,不存在再加锁处理
if (instance == null){
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
//静态初始化
private static readonly Singleton instance= new Singleton();
public static Singleton GetInstance(){
return instance;
}
使用者不关心对象的实例化过程,只关心对象的获取。工厂模式使得产品的实例化过程和消费者解耦
public interface Sender{ public void send(); }
public class MailSender implements Sender {
@Override
public void send() {
System.out.println("this is mailsender!");
}
}
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("this is sms sender!");
}
}
public class SendFactory {
public Sender produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
} else {
return null;
}
}
//若还有其他产品 则在工厂里加对应的 produce 方法
}
主要解决在软件系统中一个复杂对象的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
@Data
class Product {
private String name;
private String price;
// Product 的建造者 Builder
public static class Builder{
public static Builder builder(){
Builder builder = Builder();
}
private Product product = new Product();
public Builder name(String name){ product.name = name; return this;}
public Builder price(String price){ product.price = price; return this; }
//返回产品对象
public Product build() { return product; }
}
}
连通上下游功能。一般是现有的功能和产品要求的接口不兼容,需要做转换适配。平时见到的 PO,BO,VO,DTO 模型对象之间的相互转换也是一种适配的过程
//类的适配器模式
public class Source {
public void sayHello() {
System.out.println("lwl:hello!");
}
}
public interface Targetable {
/* Source方法相同 */
public void sayHello();
/* 新增的方法 */
public void hi();
}
// Source 用 Adapter 适配成 Targetable
public class Adapter extends Source implements Targetable {
@Override
public void hi() {
System.out.println("csc:hi!");
}
}
//对象的适配器模式
public class Source {
public void sayHello() {
System.out.println("lwl:hello!");
}
}
public interface Targetable {
/* Source方法相同 */
public void sayHello();
/* 新增的方法 */
public void hi();
}
// Source的对象适配成 Targetable
public class Adapter implements Targetable {
private Source source;
public Adapter(Source source){ this.source = source; }
public void sayHello(){ source.sayHello(); }
@Override
public void hi() {
System.out.println("csc:hi!");
}
}
增强对象功能,动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删)
public interface Show(){ public void acting(); }
public class Artist implements Show {
public void acting(){
System.out.println("lwl 在唱歌!");
}
}
public class DecoratorArtist implements Show{
Artist artist;
DecoratorArt(Artist artist){
this.artist = artist;
}
public void acting(){
System.out.println("lwl 在弹钢琴!"); //增强的功能
this.artist.acting();
System.out.println("表演完毕!"); //增强的功能
}
}
代理类是客户类和委托类的中介,可以通过给代理类增加额外的功能来扩展委托类的功能,这样只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则
public class Artist implements Show {
public void acting(){
System.out.println("lwl 在唱歌!");
}
}
public class ProxyArtist implements Show{
Artist artist;
ProxyArtist(){
this.artist = new Artist();//屏蔽了 artist 对象的创建
}
public void acting(){
System.out.println("lwl 在弹钢琴!"); //增强的功能
this.artist.acting();
System.out.println("表演完毕!"); //增强的功能
}
}
public class Demo {
public static void main(String[] arg){
Show show = new ProxyArtist();
show.acting();
}
}
桥接模式侧重于功能的抽象,从而基于这些抽象接口构建上层功能。一般的java 项目都会将接口和实现分离原因,就是基于桥接模式。提高了系统的扩展能力,当引用的底层逻辑有不同的设计实现时,继承抽象接口重新实现一套即可,旧的不变,符合代码设计的开闭原则
public interface FileSystem(){
public void open(int file);
public String loading(int file);
public void store(int file, String data);
}
//网络上的文件系统
public class NetFileSystem implements FileSystem {
public void open(int file){ System.out.println(" netfile opening...."); }
public String loading(int file) {System.out.println(" net loading ...."); }
public void store(int file, String data) {System.out.println(" send to network ...."); }
}
//磁盘文件系统
public class DiskFileSystem implements FileSystem{
public void open(int file){ System.out.println(" disk opening...."); }
public String loading(int file) {System.out.println(" disk loading ...."); }
public void store(int file, String data) {System.out.println(" write back disk ...."); }
}
public class Linux {
FileSystem fileSystem;
//底层功能提供接口,桥接模式:功能和具体实现分离
//可以桥接 NetFileSystem 或者 DiskFileSystem 作为文件系统
public void set(FileSystem fileSystem){ this.fileSystem = fileSystem; }
//上层功能读数据
public String read(int file){
fileSystem.open(file);
... // Linux 自己的系统功能
fileSystem.loading(file);
...
}
//上层功能写数据
public String write(int file, String data){
fileSystem.open(file);
....
fileSystem.store(file,data);
}
}
多个对象共享某些属性。在创建有大量对象时,可能会造成内存溢出,把其中共同的部分抽象出来,如果有相同的请求,直接返回在内存中同一份属性,避免重新创建
public class ConnectionPool {
private Vector<Connection> pool;
/*公有属性*/
private String url = "jdbc:mysql://localhost:3306/test";
private String username = "root";
private String password = "root";
private String driverClassName = "com.mysql.jdbc.Driver";
public ConnectionPool() {
pool = new Vector<Connection>(poolSize);
for (int i = 0; i < poolSize; i++) {
Class.forName(driverClassName);
// 每一个 conn 共享了 driverClassName ,url, username, password 等属性
Connection conn = DriverManager.getConnection(url, username, password);
pool.add(conn);
}
}
....
}
public class DAO {
public void queryData(){
System.out.print(" query data ")
}
}
public class Deal {
public void dealData(){
System.out.print(" dealing data ")
}
}
public class Sender {
public void send(){
System.out.print(" send data ")
}
}
public class Service(){
private DAO dao;
private Deal deal;
private Sender sender;
//封装 DAO,Deal,Sender 的功能,统一对外提供服务
public void reponse(){
dao.queryData();
deal.dealData();
sender.send();
}
}
策略模式侧重于不同的场景使用不同的策略。在有多种算法相似的情况下,解决 if...else 所带来的复杂和难以维护
// 上学的策略
abstract class Strategy{
private static final Map<Integer,Strategy> strategyMap = new ConcurrentHashMap<>();
public Strategy(){
strategyMap.put(getType(), this);
}
public static Strategy routing(int type){
return strategyMap.get(type);
}
abstract int getType();
abstract void method(); //留待子类实现差异
}
//跑路去学校
class RunningStrategy extends Strategy{
int getType() { return 0; }
void method() { System.out.println(" Run to school "); }
}
//公交去学校
class BusStrategy extends Strategy{
int getType() { return 1; }
void method() { System.out.println(" Go to school by bus "); }
}
//飞去学校
class FlyStrategy extends Strategy{
int getType() { return 2; }
void method() { System.out.println(" Fly to school "); }
}
class Context{
//使用不同的策略
void method(int strategy){
Strategy.routing(strategy).method();
}
}
和享元模式有一定的相似处,享元模式侧重于属性的共享,而且是结构上的引用,不一定需要继承;而模板方法是共享相同行为,一定有继承行为
abstract class AbstractHandler{
// handle是抽象出来的共同逻辑
void handle(String data){
System.out.println("通用逻辑1...");
stepOne(data);
System.out.println("通用逻辑2...");
stepTwo(data);
System.out.println("通用逻辑3...");
}
abstract void stepOne(String data); //留待子类实现差异
abstract void stepTwo(String data); //留待子类实现差异
}
class HelloHandler extends AbstractHandler{
@Override
void stepOne(String data) {
System.out.println("hello: "+data);
}
@Override
void stepTwo(String data) {
System.out.println("hi: "+data);
}
}
循环处理多个相同对象,用来遍历集合或者数组
//迭代的抽象接口
public interface Iterator {
//前移
public Object previous();
//后移
public Object next();
public boolean hasNext();
}
// 数组的迭代类
public class ArrayIterator implements Iterator {
private Object[] datas;
private int cur = 0;
public ArrayIterator(Object[] datas){
this.datas = datas;
}
public String previous() {
if(cur > 0){ cur--;}
return datas[cur];
}
public Object next() {
if(cur < datas.length-1){ cur++;}
return datas[cur];
}
public boolean hasNext() {
return pos < datas.length-1 ? true :false;
}
}
负责处理上游的传递下来的对象,并传递给下一个处理者
abstract class Handler<T,R> {
private Handler<R,?> next;
abstract R handle(T data);
public void setNext(Handler<R, ?> next){ this.next = next; }
public void loopHandle(T data){
R result = this.handle(data);
if(next!=null && result!=null ) { next.loopHandle(result); }
}
}
//负责问候
class HelloHandler extends Handler<String, Integer> {
Integer handle(String data) {
System.out.println(data + " hello! ");
return 10;
}
}
//负责计数
class CountHandler extends Handler<Integer, Double> {
Double handle(Integer data) {
System.out.println(" it is " + data);
return 2.0;
}
}
public class demo{
public static void main(String[] args){
HelloHandler hello = new HelloHandler();
CountHandler count = new CountHandler();
hello.setNext(count);
hello.loopHandle("lwl");
}
}
事件通知: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知
//观察者
public abstract class Observer<T> {
public abstract void update(T data);
}
// 被观察对象
public class Subject<T> {
private List<Observer<T>> observers = new ArrayList<>();
private T state;
public void deal() {
....// 逻辑处理
//如果修改了 state,通知观察者
if(...) notifyAllObservers();
}
//增加一个观察观察
public void observe(Observer<T> observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for (Observer<T> observer : observers) {
observer.update(state);
}
}
}
不同的状态不同的响应,实现状态之间的转移
interface State<T> {
//当前状态进行处理数据,并返回下一个状态
abstract State<T> action(T data);
}
@Data
class Context<T>{
private State<T> state;
public void invoke(T data){
state != null ? state = state.action(data) : System.out.println(" nothing " + data);
}
}
// HelloState -> HiState
class HelloState implements State<String>{
public State<String> action(String data) {
System.out.println("hello!" + data);
return new HiState();
}
}
// HiState -> FineState
class HiState implements State<String>{
public State<String> action(String data) {
System.out.println("how are you ?" + data);
return new FineState();
}
}
//最后的状态
class FineState implements State<String>{
public State<String> action(String data) {
System.out.println("I am fine!");
return null;
}
}
public class demo{
public static void main(String[] args){
Context<String> context = new Context<>();
context.setState(new HelloState());
context.invoke("lwl");
context.invoke("lwl");
context.invoke("lwl");
context.invoke("lwl");
}
}
记录上一次的状态,方便回滚。很多时候我们是需要记录当前的状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,恢复到原先的状态
@Data
public class Memento {
private String state;
public Memento(String state){ this.state = state; }
}
@Data
public class Storage {
private String value;
public void storeMemento(){
return new Memento(value);
}
public void restoreMemento(Memento memento){
this.value = memento.getValue();
}
public void action(){ System.out.println(" Storage类逻辑运行 ");}
}
public class MementoPatternDemo {
public static void main(String[] args) {
Storage storage = new Storage();
storage.setValue(1);
storage.storeMemento();//备忘,一下
storage.action();//....逻辑运行
restoreMemento(Memento memento);//使用备忘录的恢复状态
}
}