设计模式 - KOkkmiao/note GitHub Wiki

目录

  • 原理规范
  • 工场模式
  • 策略模式
  • 装饰者模式
  • 原型模式
  • 模板方法模式
  • 外观模式
  • 建造者模式
  • 观察这模式
  • 状态模式
  • 适配器模式
  • 备忘录模式
  • 组合模式
  • 迭代器模式
  • 单例模式
  • 桥接模式
  • 命令模式
  • 责任链模式
  • 中介模式
  • 享元模式 (没啥用)
  • 解释器模式

原理规范

1 面向对象

2 抽取变化的内容

3 单一职责原则 (一个类应该仅有一个引起他变化的原因)

4 对类、模块、函数等扩展开放,对修改封闭。

5 LSP 里氏原则

1 如接口的定义,将实现类的共同特征进行抽象,在实现类发生变化后不用修改之前的代码。
2 通过集成的方式,将父类的行为进行扩展。 但是之前代码调用的还是父类的方法名

6 迪米特法则

7 外观模式

8 松耦合尽量使用类之间的包含 不要去使用继承关系

如手机品牌就是手机品牌,手机原件,手机软件,和手机是包含关系
手机<>——品牌,原件,软件

简单工场模式

工厂模式中定义好一些类的生产方式如通过一个typ来进行生成不同的类,或者其他的判断条件来生成对应的实体类
/**
 * type: 上等人、中等人、下等人.....
 */
static User getUser(String type){
    User  resultUser = null;
    if(type==null&&"".equal(type)){
        throw new NullException("type is not null");
    }
    switch(type){
        case '上等人':
         resultUser = new User("上等人");
         break;
        case '中等人':
         resultUser = new User("中等人");
         break;
        default:
         resultUser = new User("普通人");
    }
    return resultUser;
}

抽象工厂模式

将简单方法模式中的 switch case 分开,同时只需要在使用的地方修改类的类型即可
将 switch case 放到调用方。
/**
*抽象类
*/
abstract class AbstractFactory{
    //提供给子类去实现
    AbstractInterface getAbstract();
    
} 
/**
*类的实现
*/
class AbstractClazz implements AbstractInterface{
     void method1(){//do something}
    void method2(){//do something}
}
/**
*要生成的工厂结果类的抽象或者是接口
*/
interface AbstractInterface{
    void method1();
    void method2();
    ...
}

策略模式 [在设计模式图文件看图]

1 通过接口暴露出去策略模式(简易的) 

2 通过模板方法模式,将基本的计算方式实现后通过抽象方法的方式提供给子类来实现

3 通过接口或者抽象类的方式将函数的计算暴露出去,可通过实现或者继承的方式来添加新的算法

别的解释

定义算法家族,分别封装起来,让他们之间可以互换,此模式让算发的变化,不会影响到使用算法的调用方。

装饰者模式

1 装饰者、 被装饰者、实现装饰者模板接口的类
装饰者和被装饰者实现共同的接口
例如
    通过接口 InputStream
    被装饰者 FileInputStream
    装饰者实现 BufferedInputStream
                          FileInputStream-->InputStream
                       继承                实现                
    BufferedInputStream——>FilterInputStream-->InputStream
    
    BufferedInputStream 包装 FileInputStream提供 read 的操作增强

原型模式

提供 clone 的一种模式

模板方法模式

定义一个算法的股价,将一些步骤延迟到子类去实现。可以在不改变模板算法的前提下执行算法的某些特定步骤

外观模式

将一些系列的子类调用分配到一个类中来统一调用,同时向外暴露接口
    class A{
        void method(){
            sout("买A数据")
        }
        void method2(){
            sout("卖A数据")
        }
    }
    class B{
        void method(){
            sout("买B数据")
        }
        void method2(){
            sout("卖B数据")
        }
    }
    class AB{
        A a;
        B b;
        public AB(A a,B b){
            this.a = a;
            this.b = b;
        }
        void methodBuy(){
            a.method();
            b.method();
        }
          void methodSell(){
            a.method2();
            b.method2();
        }
    }
    /**
    *如果不这样写的情况下 需要分别去调用a和b的买卖接口
    *更简化了A B 类的使用
    */

建造者模式

如果需要生成的类很复杂,需要多个组件进行配合以防遗漏。
class Builder{
    //客户端需要调用此方法来获取建造者最终创建出来的对象
    public Product Builder(BuilerTemplete p){
        p.methodMain();//构建
        p.getResult();//获取结果
    }
}
abstract class BuilerTemplete{
    public Project DEFA
    //持有构建类
    public Product p ;
    
    public BuilerTemplete(Product p){
        this.p=p;
    }
    
    public void methodMain(){
        //构建基本需要执行的统一方法
        method1();
        method2();
        method3()
    }
    //构建需要的内容 方法
    public abstrct void method1();
    public abstrct void method2();
    public abstrct void method3();
    public Product getResult(){
        retrun p;
    }
}
class BuilderTempleteA extends BuilerTemplete{
//这些方法都是抽象方法必须时间。为以防忘记实现
    public abstrct void method1(){对 p做操作}
    public abstrct void method2(){对 p做操作}
    public abstrct void method3(){对 p做操作}
    
}

观察者模式

使用场景 1 如果 A 类中的变化需要通知,或者需要修改一系列类的内容时。则可用此模式
2 在不同的通知过程中可以在 notify 中添加一个 Eventhandler 类似于 call back 的方式将需要
通知观察者的方式换成接口。
interface EventHandler{
    void excutor();
}
/**通过接口来定义观察者的执行行为的好处是,在 add *的时候将每个不同的实体类想执行的方法自己去定义,通提供统一接口。 如
*/
class Subject{
    List<EventHandler> list = new ArrayList<EventHandler>();
    public void add(EventHandler e){
        list.add(e);
    }
    public void notify(){
        list.foreach(EventHandler::excutor);
    }
}
class Client{
    public static void main(String[] args){
        see = new see
        //这样就可以让观察者自己定义自己想执行的方法
        subject.add(()->{see.call}); 
        look = new look
        subject.add(()->{look.look});
    }
}

状态模式

状态模式 是将繁琐的if eles  以一个 state 状态类来获取if else 的结果。只需要获取state 的状态就可以了。 且 state
类相当月一个抽象接口类,在 state 中的实现类发生变化后,客户段这边是无感的,同时解决了
复杂的判断结构体

适配器模式

其实说白了就是将类封装在接口中,向外暴露出接口,让当前类有两个的接口功能,

使用范围

在 A B 两个类设计完好之后在不改动原有类的基础上,抽象出来一个借口,来将两个类
需要使用的接口进行抽象化
/**当前需要调用的类,却没有 B 类的方法的功能。
 * 1 简单的方法,将 B 类中的方法实现一遍
 * 2 将 A 类中的持有 B 类的引用同时在 A 类中定义 B 类的同名方法
 * 3 将 A B 类中需要调用的方法进行抽象出接口,同时实现接口类
 * C 这样就可以在调用的时候就能将 C 类进行方法的扩充或修改,
 * 符合扩展开放,修改封闭原则,
 * 好处是将 A 类和 B 类之间没有代码耦合,同时在一定成度上将 A B 联系在了一起
 */
 class A {
     
     public void method(){
         
     }
 }
 class B {
     
     public void method(){
         
     }
 }
 abstract class C{
     
     public void methodA(){
         
         
     }
     public void methodA(){
         
         
     }
 }
 class C extends C{
     public void methodA(){
         
         
     }
     public void methodA(){
         
         
     }
     
 }
 

备忘录模式

将类的状态属性进行保存,在类想要恢复到上一个记录的时候可以进行恢复。
class A
{

    private String state;
    private int version;
    public void createMo(){
        memory.setMemory(this,new MemoryVersion(version++,state));
    }
    //根据版本来进行回归状态
    public void reset(int version){
        memory.getMemory(this).version;
        
    }
//作为匿名内部类存在
class MemoryVersion implements MeomeryModel{
    pirvate Integer version;
    private String state;
    public MemoryVersion(Integer version,String state){
        this.version = version;
        this.state = state;
    }
    set{version,state}
    get{version,state}
}
}
interface MemoryModel{
    int version();
    String state();
}
final class memory{
    //缓存所有的state
    private static  Map<Class,MemoryModel> memory = new HashMap<>();
    public static void getMemory(Class clazz,int version){
        if(Clazz==null){
            throw new NullPointException("this clazz Class is null ");
        }
        return memory.get(clazz);
    }
}
    

组合模式

在设计对象是以部分和整体的体现形式的时候,具有包含关系,等相关的条件,则可用组合模式
abstract class compoent{
    private String name;
    Compoent add(compoent  con);
    void  remove (Compoent con);
    .....
}
/**这里是组件的实现 实现同的组件。
*但因为有包含关系则需要有一个组件作为根组件
*/
class compoent extends compoent{
  List<compoent> list = new Arraylist();
  Compoent add(compoent  con){
      list.add(com);
      return this;
  }
  void  remove (Compoent con){
      
  }
  class leaf extends compoent{
   Compoent add(compoent  con){
    return null;
   
  }
  void  remove (Compoent con){
      
  }   
  }

}

迭代器模式

单例模式

单例模式注意的点是 在双 if 判断在多线程的条件下,通过 volatile 关键字进行对象限定。
原因是因为对象的创建和赋值是两个操作。会导致指令重排,可能 A 已经拿走了创建的对象但是
还没有进行赋值操作
A a = null;
a = new A();

桥接模式

将产品中的关系各自分类,不进行耦合,同时抽象出来产品的执行功能
类似于模板方法模式+接口策略模式

命令模式

将需要执行的人通过队列进行整理好之后再去执行
同时指令需要传入要执行的人

命令模式的好处

1 在收集命令的时候可以有对应的日志,
2 收集过程中将命令统计好之后再去执行 
abstract class Command{
    //指定需要执行的人
    protected Receiver receiver;
    public Command(Receiver receiver){
        this.receiver = receiver;
    }
    //命令执行的方式 
    abstract void execute();
}
//命令的实现 和执行人的关联
class CommandInovke{
public CommandInovke(Receiver receiver){
    super(receiver)
}
    //真实执行方法
    void execute(){
        receiver.action();
    }
}
//命令收集者
class ReceiverCommamd{
    List<Command> list = new Arraylist();
    method:
    {list.set ;
    list.remove;
    }
    void inovker(){
        list.foreach(Command::excecute);
    }
}
class Receiver{
    void action(){
        //执行命令
    }
}

责任链模式

在抽象类中持有下一个责任的引用在子类中获取到父类中的引用产生链式调用
类似于组合模式,
abstract class Handler{
    private Handler handler
    public void set Handler(Handler handler){
        this.handler = handler
    }3123
    //当前责任执行完毕折后再去执行
    abstract void next(Request req);
}
..... 实现类,Request 参数

中介模式

在中介模式 中介者持有所有对象的引用, 且对象也持有中介者,这样在
用户1中调用数据 通过中介者来进行转发
//中介者
interface A {
    void send (String message,Class name)
}
class B implements A{
    private College
}
//抽象 公用类
abstract class College{
    //每个类都有共同的中介
    private A a;
    public College(A a){
        this.a = a;
    }
}
//实际类
class collegeA extends College{
    public CollegeA(A a){
        super(a);
    }
    public void send(){
        
    }
}

享元模式

就是单例和多例的一种模式。

解释器模式

模板方法模式
⚠️ **GitHub.com Fallback** ⚠️