当前位置: 首页 > article >正文

设计模式-读书笔记2

结构型模式

适配器模式 不兼容结构的协调 220v接入20v的笔记本电脑 别名包装器 Wrapper

适配器类Adapter 适配者类Adaptee 目标抽象类 Target

//demo1
class Adapter extends Target{
    private Adaptee  adaptee; //维持对一个适配者对象的引用
    public Adapter (Adaptee adaptee){
        this.adaptee = adaptee;
    }
    public void request(){ // 转发调用
        adaptee.specificRequest();
    }
}

当target 和adaptee双向调用时,双向适配器模式

//demo2
class Adapter implements Target,Adaptee{
    private Adaptee  adaptee; //同时维持对适配者和目标类的引用
    private Target target;
    public Adapter (Adaptee adaptee){
        this.adaptee = adaptee;
    }
    public void request(){ // 转发调用
        adaptee.specificRequest();
    }
}

缺省适配器模式:当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求,它适用于不想使用一个接口中的所有方法的情况,又称单接口适配器模式

桥接模式 处理多维度变化 颜色、系统 分类抽象接口和实现

//demo1
//实现类接口
interface ImageImp{
    public void doPaint(Matrix m); //显示像素矩阵m
}
//具体实现类
class WindowImp implements ImageImp{
    public void doPaint(Matrix m){
        sout("在windows系统上显示")
    }
}
//抽象类
abstract class Image{
    protected ImageImp imp; //定义实现类接口对象
    public void setImageImp(ImageImp imp){
        this.imp = imp;
    }
    public abstract void parseFile(String fileName); //声明抽象业务方法
}
//扩充抽象类
class JPGImage extends Image{
    public void parseFile(String fileName){
        Matrix m = new Matrix;
        imp.doPaint(m); //调用实现类的方法
        sout("格式为jpg")
    }
}

组合模式 树形结构的处理 处理文件夹及下面的文件

定义一个抽象构建类,既可以代表叶子,又可以代表容器

//demo1
//抽象构件
abstract class Component{
    public abstract void add(Component a); //新增
    public abstract void del(Component a); //删除
    public abstract void operation(); //业务方法
}
//叶子构件
class Leaf extends Component{
    add。。。。
    。。。。
}
//容器构件
class Composite extends Component{
    private ArrayList<Component> list = new ArrayList<Component>();
    add{list.add(c)}。。。。
    。。。。
    public void operation(){
        //容器构件具体业务方法的实现
        //递归调用成员构件的业务的方法
        for(Object obj:list){
            ((Component)obj).operation();
        }
    }
}

P162 12.5 22:08留

透明组合模式:抽象构件类Compenent 有所有方法,提供默认实现

安全组合模式:抽象构件类Compenent 没有管理成员对象的方法,如叶子节点leaf不需要的add等方法

装饰模式 扩展系统功能 对象结构型

动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更加灵活

抽象构件Compoent:是具体构件和抽象装饰类地共同父类

具体构件ConcreteComponent:

抽象装饰类:Decorator 给具体构件增加职责,但具体职责在其子类中实现

具体装饰类:ConcreteDecorator

//demo1抽象装饰类的设计
class Decorator implements Component{
    private Component component; // 维持一个对抽象构件对象的引用,注入一个抽象构件类型的对象
    public Decorator(Component component){
        this.component = component;
    }
    public void operation(){
        component.operation(); //调用原有业务方法
    }
}
//具体装饰类中
class ConcreteDecorator extends Decorator{
   public ConcreteDecorator(Component component){
        super(component);
    }
    public void operation(){
        super.operation(); //调用原有业务方法
        addedBehavior(); //调用新增业务方法
    }
    public void addedBehavior(){
        .....
    }
}
//使用
Component component, componentSB;  //使用抽象构件定义
component = new Window(); // 定义具体构件
componentSB = new ConcreteDecorator(); //定义装饰后的构件
componentSB.display();
//也可以
Component componentBB;  //全部使用抽象构件定义
componentBB = new ConcreteDecorator2(componentSB); //将装饰了一次之后的对象继续注入到另一个装饰类中进行第2次装饰

透明装饰模式

上面使用抽象构件类型定义对象,而不是具体构件类型,如

ConcreteDecorator2 componentBB = new ConcreteDecorator2(componentSB);

但是这无法调用具体装饰类中的新增行为

半透明装饰模式

Component component; //使用抽象类型定义
component = new Window();
ConcreteDecorator componentSB = new ConcreteDecorator();  //使用具体装饰类型定义

这不能实现对一个对象的多次装饰(传入调用)

外观模式 提供统一入口 facade

外观角色

//demo1
class Facade{
    private SubSystemA obj1 = new SubSystemA();
    private SubSystemB obj2 = new SubSystemB();
    public void method(){
        obj1.method();
        obj2.method();
    }
}

设计为单例类,定义了一个静态的Facade类型的成员变量instance,其构造函数为私有private

如果要一个子系统变为另一个,原有不再使用,这需要引入一个抽象外观类,客户端针对抽象外观类编程,而在运行时再确定具体外观类

//demo1
abstarct class AbstractFacade{
    public abstract void method();
}
Class newFacade extends AbstractFacade{
    
}

享元模式 实现对象的复用,通过共享技术有效支持大量细粒度对象的复用

FlyWeight 抽象享元类

ConcreteFlyWeight 具体享元类

UnsharedConcreteFlyWeight 非共享具体享元类

FlyweightFactory 享元工厂类,通常只有一个

//demo1
class FlyweightFactory {
    //定义一个HashMap用于存储享元对象,实现享元池
    private HashMap flyweights = new HashMap();
    public FlyWeight getflyweight(String key){
        //如果对象存在,则直接从享元池获取
        if(flyweights.containskey(key)){
            return (Flyweight)flyweights.get(key);
        }else{
            //如果对象不存在,先创建一个新的对象添加到享元池中,然后返回
            FlyWeight fw = new ConcreteFlyWeight();
            flyweights.put(key, fw);
            return fw;
        }
    }
}

内部状态:“a"始终是"a”

外部状态:"a"有的是红色的

//demo2
class FlyWeight{
    //内部状态inState作为成员变量,同一个享元对象其内部状态是一致的
    private String instate;
    public FlyWeight (String instate){
        this.instate = instate;
    }
}
//demo3
//外部状态exstate 在使用时由外部设置,不保存在享元对象中,即使是同一个对象,在每一次调用时可以传入不同的外部状态
public void operation(String exstate){
    
}

单纯享元模式:所有具体享元类都是可共享的

符合享元模式:其中包含的每个单元享元类外部状态相同,其内部状态不同,符合享元对象本身不共享

//demo4
String s1 = "ab";
String s2 = "a"+"b";
s1 == s2  true

代理模式 对象的间接访问

Proxy类

//demo1
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

返回一个动态创建的代理类的实例

第一个参数是代理类的类加载器

第2个参数是代理类所实现的接口列表(与真实主题类接口列表一致)

第3个参数是代理类所指派的调用处理程序类

//demo2
interface AbstractDao //抽象主题角色
class UserDaoo implements AbstractDao {} //真实角色  有个findUserById方法
//自定义请求处理程序类
class DaoLogHandler implements InvocationHandler{
    private Object object;
    public DaoLogHandler(){};
    public DaoLogHandler(Object object){
        this.object = object;
    }
}

实现invoke方法,调用在真实主题类中定义的方法

//demo3
public Object invoke(Object proxy, Method method, Object[] args) throw Throwable{
    //proxy是代理类的实例
    //method需要代理的方法
    //args代理方法的参数数组
    Object result = method.invoke(object, args);   // object转发调用
    return null;
}

实现

//demo4
AbstraceDao dao = new UserDao();
InvocationHandler handler = new InvocationHandler(dao);
AbstraceDao proxy = null;
//动态创建代理对象,用来代理一个AbstractUserDao类型的真实主题对象
proxy = (AbstractDao)Proxy.newInstance(AbstraceDao.class.getClassLoader(), new Class[]{AbstractDao.class}, handler);
proxy.findUserById(); // 调用代理对象的业务方法

远程代理:访问远程主机

虚拟代理:如上,例如一个对象需要很久时间才能完成加载,用一个资源少的对象来代理一个消耗资源多的对象

保护代理:访问权限

缓冲代理:提供临时存储空间,以供多个客户端共享结果

智能引用代理:提供额外操作

与装饰不同,它目的在动态增加功能,且新职责在同一个问题域,而代理是不同问题域,目的在控制对象的访问

行为型模式

职责链模式 请求的链式处理

请求处理对象仅需维持一个指向后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的互相连接

//demo1
abstract class Handler{
    //维持对下家的引用
    protected Handler succesor;
    public void setSuccesor(Handler succesor){
        this.succesor = succesor;
    }
    public abstract void handleRequest(String request){
        if(请求满足条件){
            //处理请求
        }else{
            this.succesor.handlerRequest(request); //转发请求
        }
    }
}

命令模式 请求发送者与接收者解耦

//demo1
//抽象命令类
abstract class Command{
    public abstract void execute();
}
//调用者
class Invoker{
    private Command command;
    //构造注入
    public Invoker(Command command){this.command = command}
    //设值setter注入
    public void setCommand(Command command){this.command = command}
    //业务方法 用于调用命令类的execute方法
    public void call(){
        command.execute();
    }
}
//具体命令类 
class ConcreteCommand extends Command{
    private Receiver receiver; //维持一个对请求接收者对象的引用;
    public void execute(){
        receiver.action();  //调用请求接收者的处理方法
    }
}
class Receiver{public void action(); //具体操作}

将请求发送者和接收者完全解耦

命令队列:将多个请求排队,增加一个CommandQueue类

//demo2
class CommandQueue{
    //定义一个ArrayList来存储命令队列
    private ArrayList<Command> commands = new ArrayList<Command>();
    public void addCommand ~ 
    //循环调用每一个命令对象的execute()方法
    public void execute(){
        for(Object command:commands){
            ((Command)command).execute();
        }
    }    
}
//请求发送者Invoker中
private CommandQueue cq;
//调用方法
public void call(){
    cq.execute();
}

解释器模式

自定义语言的实现

//demo1
//抽象表达式 
abstract class AbstractExpression{
    public abstarct void interpret(Context ex);
}
//终结符表达式
class TerminalExpression extends AbstractExpression{
    public void interpret(Context ctx){}
}
//非终结符表达式
class NonTerminalExpression extends AbstractExpression{   //一个类对应一个规则
    private AbstractExpression left;
    private AbstractExpression right;
    //构造注入.....
    public void interpret(Context ctx){
        //递归调用每一个组成部分的interpret方法,在递归调用时指定组成部分的连接方式,即非终结符的功能
    }
}

迭代器模式 遍历聚合对象中的元素 存储数据和遍历数据分离

提供一种方式来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标cursor

//demo1
//抽象迭代器
interface Iterator{
    public void first();
}
//具体迭代器
class ConcreteIterator implements Iterator{
    private ConcreteAGG objects;   //维持一个对具体聚合对象的引用,以便于访问存储在聚合对象中的数据
    private int cursor; // 定义一个游标,用于记录当前访问位置
    public ConcreteIterator(ConcreteAGG objects){
        this.objects = objects;
    }
    public void first(){
        ......
    }
}
//抽象聚合类
interface AGG{
    Iterator createIterator();
}
//具体聚合类
class ConcreteAGG implements AGG{
    public Iterator createIterator(){
        return new ConcreteIterator(this);
    }
}
//或在具体聚合类中使用内部类实现迭代器
private class Itr implements Iterator<E>{
    int cursor=0;
    。。。。。
}

如JDK内置的迭代器一样,Collection接口中有add方法 Iterator iterator()

以上不支持逆向遍历 ListIterator接口可支持

ListIterator i = c.listIterator();

P298 记录昨天下午看的内容 20:30留

中介者模式 协调多个对象之间的交互 网状变为星型

抽象中介者

//demo1
abstract class Mediator{
    protected ArrayList<Colleague> colleagues;  // 用于存储同事对象
    //注册方法,用于增加同事对象
    public void register(Colleague colleague){
        colleagues.add(colleague);
    }
    //声明抽象的业务方法
    public abstract void operation();
}
//具体中介者
class ConcreteMediator extends Mediator{
    //实现业务方法,封装同事之间的调用
    public void operation(){
        .....
        ((Colleague)colleagues.get(0)).method(); //通过中介者调用同事类的方法
    }
}
//抽象同事类
abstract class Colleague{
    protected Mediator mediator; //维持一个抽象中介者的引用
    //构造注入
    public Colleague(Mediator mediator){
        this.mediator = mediator;
    }
    public abstract void method();   //声明自身方法,处理自己的行为
    public void method2(){
        mediator.operation();  // 定义依赖方法,与中介者进行通信
    }
}
//具体同事类
class ConcreteColleague extends Colleague{
    public ConcreteColleague(Mediator mediator){
        super(mediator);
    }
    //实现自身方法
    public void method1(){.....}
}

增加新的同事类:

法1:直接在具体中介者中改

法2:增加具体中介者的子类,进行方法覆盖

备忘录模式 撤销功能的实现 别名Token

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就能在以后将对象恢复到原先保存的状态

//demo1
//原发器
public class Originator{
    private String state;
    public Originator(){};  // 创建备忘录对象
    public Memento createMemento(){
        return new Memento(this);
    }
    //根据备忘录对象恢复原发器状态
    public void restoreMemento(Memento m){
        state = m.state;
    }
    setState......getState.....
}
//为了保证备忘录的封装性,要与原发器一个包
class Originator{
    private String state;
    public Memento(Originator o){  //只由原发器控制,而不是负责人
        state = o.getState();
    }
    setState。。。。getState....
}
//负责人
public class Caretaker{
    private Memento memento;
    public Memento getMemento(){
        return memento;
    }
    public void setMemento(Memento memento)......
}

如果要多次撤销,负责人中定义ArraysList集合来存储多个备忘录

private ArrayList mementoList = new ArrayList();

观察者模式 对象间的联动

一对多 每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新

别名:发布-订阅 模型-视图 源-监听器 从属者

//demo1
//目标
abstract class Subject{
    //定义一个观察者集合用于存储所有观察者对象
    protected ArrayList observers<Observer> = new ArrayList();
    //注册方法,用于向观察者集合中增加一个观察者
    public void attach(Observer observer){
        observers.add(observer);
    }
    //注销方法   删除  detach   remove
    //声明抽象通知方法
    public abstract void notify();
}
//具体目标类
class ConcreteSubject extends Subject{
    //实现通知方法
    public void notify{
        //遍历观察者集合,调用每一个观察者的响应方法
        for(Object obs:observers){
            ((Observer)obs).update();
        }
    }
}
//抽象观察者
interface Observer{
    //声明相应方法
    public void update()
}
//具体观察者
class ConcreteObserver implements Observer{
    实现.......
}

java.util.Observable 接口只有一个方法,充当抽象观察者 void update(Observable o, Object args)

java.util.Observable类,包含新增删除

发布者:事件源

订阅者:事件监听器

通过事件对象传递

P340 21:48 留

对象状态及其转换 状态模式

允许一个对象在其内部状态时,改变它的行为,对象看起来似乎修改了它的类

//demo1
//抽象状态类
abstract class State{
    //声明抽象业务方法,不同的具体状态类可以用不同的方法实现
    public abstarct void handle();
}
//具体状态类
class ConcreteState extends State{
    public void handle(){
        //具体方法实现代码
    }
}
//环境类,实际上是真正拥有状态的对象
class Context{
    private State state; // 维持一个对抽象状态对象的引用
    private int value; //其他属性值,该属性值的变化可能会导致对象状态发生变化
    //设置状态对象
    public void setState(State state){
        this.state = state;
	}
    public void request(){
        //其他代码
        state.handle(); //调用对象的业务方法
    }
}

状态的转换,2种方式:一是统一由环境类来负责

//demo2
public void changeState(){
    //判断属性值,根据数据值进行状态转换
    if(value==0){
        this.setState(new ConcreteStateA());
    }else if(value==1){
        this.setState(new ConcreteStateB());
    }
}

二是具体状态类负责

//demo3
public void changeState(Context ctx){
    //根据环境对象中的属性值进行状态转换
    if(ctx.getValue()==1){
        ctx.setState(new ConcreteStateB());
    }elseif .......
}

共享状态:定义为环境类的静态成员对象,比如开关要么开,要么关

算法的封装与切换 策略模式 policy

将每一个算法封装起来,并让它们互相切换

//demo1
//抽象策略类
abstract class AbstractStrategy{
    public abstract void algorithm; //声明抽象算法
}
//具体策略类
class ConcreteStrategyA extends AbstractStrategy{
    //算法的具体实现
    public void algorithm(){
        //算法A
    }
}
class Context{
    private AbstractStrategy strategy; //维持一个对抽象策略类的引用
    public void setStrategy......//setter注入
    //调用策略类中的算法
    public void algorithm(){
        strategy.algorithm();
    }
}

可插入式

模板方法模式 定义算法的框架

子类可以不改变一个算法的结构,即可重定义该算法的特定步骤

//demo1
//抽象类
abstract class AbstractClass{
    public void templateMethod(){  //模板方法
        primitiveOperation1();
        primitiveOperation2();
        primitiveOperation3();
    }
    //基本方法-具体方法
    public void primitiveOperation1{
        //实现代码
    }
    //基本方法-抽象方法
    public abstract void primitiveOperation2();
    //基本方法-钩子方法,默认为空,子类实现,或者返回布尔
    public void primitiveOperation3{
        .......
    }
}
class ConcreteClass extends AbstractClass{
    public void ~2{实现代码}
    public void ~3{实现代码}
}

访问者模式 操作复杂对象结构

双重分派机制

//demo1
//抽象访问类
abstract class Visitor{
    public abstract void visit(ConcreteElementA elementA);
    public abstract void visit(ConcreteElementB elementB);
    public void visit(ConcreteElementC elementC){
        //元素C操作代码
    }
}

使用visit重载两个方法操作A、B 具体访问类中 class ConcreteVisitor extends Visitor

//demo2
//抽象元素类
interface Element {
    public void accept(Visitor visitor);
}
//具体元素类
class ConcreteElementA implements Element{
    public void accept(Visitor visitor){
        visitor.visit(this);
    }
    public void operationA(){
        //业务方法
    }
}

结束 12:10 22:00留


http://www.kler.cn/a/444344.html

相关文章:

  • 多音轨视频使用FFmpeg删除不要音轨方法
  • 7-2 排序
  • 关于小程序内嵌h5打开新的小程序
  • 深入理解ER模型:数据库设计的核心工具与应用
  • Git实用指南(精简版)
  • OpenCV圆形标定板检测算法findGrid原理详解
  • Docker+Redis单机和集群部署【非常详细】
  • Android 获取屏幕物理尺寸
  • 建站技术 | HUGO + GitHub 创建博客页面
  • 若依前端挂Nginx、打包部署运行!!!!
  • C# 项目无法加载 DLL“SQLite.Interop.DLL”: 找不到指定的模块
  • Leetcode 409. Longest Palindrome
  • BERT模型入门(1)BERT的基本概念
  • 条件随机场(CRF)详解:原理、算法与实现(深入浅出)
  • 【软件工程】简答题系列(山东大学·软院考试专属)
  • pytest接口关联框架封装
  • 将三个list往一个excel表的三个sheet中写入,能用多线程提高写入速度
  • Stream的并行方法parallelStream使用和常见问题
  • python飞机大战游戏.py
  • 详细指南:在Ubuntu 20.04上安装和配置Orbbec SDK及USB设备权限
  • 太速科技-428-基于XC7Z100+ADRV9009的双收双发无线电射频板卡
  • 《Django 5 By Example》读后感
  • 【uniapp】实战一人员交接班
  • 【go语言】reflect包与类型推断
  • 电视机通用遥控技术标准正式公布
  • 开源 AI 智能名片小程序源码在个人 IP 打造中的应用与价值