浅谈设计模式(二):装饰器模式|中介模式|原型模式

装饰器模式(Decorator Pattern)

装饰器模式可用来给一个类动态添加功能,将其装饰成一个新的类。这就是装饰器的概念。看到这里我们可能会想,要达到这种效果,我们用子类继承父类不就可以了吗? 没错装饰器模式,本身是一种继承的替代方案。那既然是替代方案,那么自然就有它不一样的地方。

具体区别在哪里呢? 请看

  • 装饰器模式更灵活:继承时父子类的关系是静态的,而装饰器模式是动态的,装饰类和被装饰类的关系是运行时候确认的
  • 装饰类和被装饰类的耦合关系是松散的,各自可以独立变化

下面看看具体的代码。具体过程可看注释

// 1.首先我们有一个Pen接口
public interface Pen {
  public void write();
}
// 2.Pencil类实现了Pen这个接口
public class Pencil implements Pen {
    public void write () {
        System.out.print("写");
    }
}
// 3.装饰类PencilDecorator也实现了Pen这个接口,且代理调用Pencil的方法
public class PencilDecorator implements Pen{
    Pen pen;
    public PencilDecorator(Pen pen) {
      this.pen = pen;
    }
    public void write () {
      pen.write();
    }
}
// 4.用具体装饰类继承PencilDecorator,这样就可以做扩展变化
public class BluePencilDecorator extends PencilDecorator{
    public BluePencilDecorator (Pen pen) {
        super(pen);
    }
    public void writeBlue () {
        this.write();
        System.out.println("写出来是蓝色的");
    }
}
// 同4.用具体装饰类继承PencilDecorator,这样就可以做扩展变化
public class RedPencilDecorator extends PencilDecorator{
    public RedPencilDecorator (Pen pen) {
        super(pen);
    }
    public void writeRed () {
        this.write();
        System.out.println("写出来是红色的");
    }
}
// 测试
public class Test {
    public static void main(String args []) {
       Pen pencil = new Pencil();
       RedPencilDecorator redPencil = new RedPencilDecorator(pencil);
       BluePencilDecorator bluePencil = new BluePencilDecorator(pencil);
       redPencil.writeRed();
       bluePencil.writeBlue();
    }
}

输出结果

代码的结构如下图所示

从这里我们看到了,经过PencilDecorator类这一层的隔离,Pencil类和BluePencilDecorator类/RedPencilDecorator类在一定程度上解耦,从而各自独立发展了。这就是代理模式能够替代继承的原因和它的独特优势

唉!! 等一下,好像看到了什么熟悉的东西,请看

没错,这还真就是代理模式的代码。

在这里,我们可以从两个角度去理解装饰器模式。

  • 第一,从构成上看,装饰器模式 = 代理模式 + 类继承。 也就是在代理模式的基础上,加了一堆继承[代理类]的子类,从而进行扩展变化,并且还尽量减少了和原有类的联系。
  • 第二,从功能上看,代理模式侧重的是“控制”,而装饰器模式侧重的是“扩展”。比如说,类A代理了类B,那么这两个类由于同一个接口的约束,它们的方法和实现的功能其实是一样的。而类C装饰了类D,那么这个时候类C不仅仅具备了类D的方法,同时还能加入自己的特殊逻辑。

中介者模式(Mediator Pattern)

简单的说,中介者模式是一个分散到集中的一个过程

还是看下具体的代码

// Colleague接口
public interface Colleague {
    public void handleExternal(Mediator mediator);
    public void handleInternal();
}
// 中介者接口
public abstract class Mediator {
   public Colleague A;
   public Colleague B;
   public Colleague C;
   public Mediator (Colleague A, Colleague B, Colleague C) {
       super();
    this.A = A;
    this.B = B;
    this.C = C;
  }
  public abstract void handleA ();
  public abstract void handleB ();
  public abstract void handleC ();
}
// 实现了中介者接口的中介者类,封装了不同Colleague类的对象间的复杂操作
public class ConcreteMediator extends Mediator{
    public ConcreteMediator(Colleague A, Colleague B, Colleague C) {
        super(A,B,C);
    }
    public void handleA() {
        B.handleInternal();
        C.handleInternal();
    }
    public void handleB() {
      A.handleInternal();
      C.handleInternal();
    }
    public void handleC() {
      A.handleInternal();
      B.handleInternal();
    }
}
// Colleague类在涉及其他Colleague类的复杂操作的时候,通过中介者调用
public class A implements Colleague {
    public void handleExternal(Mediator mediator) {
      mediator.handleA();
      System.out.println("---------------");
    }
    public void handleInternal() {
        System.out.println("A");
    }
}
// Colleague类在涉及其他Colleague类的复杂操作的时候,通过中介者调用
public class B implements Colleague {
    public void handleExternal(Mediator mediator) {
        mediator.handleB();
        System.out.println("---------------");
    }
    public void handleInternal() {
        System.out.println("B");
    }
}
// Colleague类在涉及其他Colleague类的复杂操作的时候,通过中介者调用
public class C implements Colleague {
    public void handleExternal(Mediator mediator) {
        mediator.handleC();
        System.out.println("---------------");
    }

    public void handleInternal() {
        System.out.println("C");
    }
}
// 测试
public class main {
    public static void main(String args []) {
        Colleague a = new A();
        Colleague b = new B();
        Colleague c = new C();
        Mediator mediator = new ConcreteMediator(a,b,c);
        a.handleExternal(mediator);
        b.handleExternal(mediator);
        c.handleExternal(mediator);
    }
}

结果输出

中介者模式理解起来,就好像

  1. 你有很多杂乱的物品摆放在房间的不同地方,找起来很不好找,现在把这些物品统一放到一个柜子里,方便集中管理。
  2. 一群人去食堂打饭的时候,如果各自去取菜那么食堂可能乱做一团,所以这时候食堂大妈就成为了“中介者”

原型模式(Prototype Pattern)

原型模式是什么?

一句话,原型模式就是克隆对象,完了。

这么简单? 这也能叫设计模式?

没错,就是这样

让我们看下代码

// 通过实现Cloneable接口并重写clone方法的方式,让Bar对象变得可克隆。
public class Bar implements Cloneable {
    String value;
    public String getValue () {
      return value;
    }
    public void setValue (String value) {
        this.value = value;
    }
    public Bar clone() {
        Bar clone = null;
        try {
            clone = (Bar)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}
// 调用clone方法可以克隆对象
public class mian {
    public static void main(String args []) {
      Bar bar = new Bar();
      Bar bar2 = bar.clone();
      bar.setValue("1");
      bar2.setValue("2");
      System.out.println(bar.getValue());
      System.out.println(bar2.getValue());
    }
}

运行结果

告诉我,原型模式的本质是什么

原型模式的本质就是—— 套娃

原型模式的优缺点

  • 原型模式的优点: 底层的二进制实现拷贝,相比起new操作可以节约性能
  • 原型模式的缺点: 构造函数没有调用,牺牲了灵活性

原文地址:https://www.cnblogs.com/penghuwan/p/12123954.html

时间: 2024-10-27 06:57:51

浅谈设计模式(二):装饰器模式|中介模式|原型模式的相关文章

浅谈设计模式1-策略模式

对于大多数面向对象的初学者来说,将思维模式从面向过程转变过来是一个比较困难的过程.很多人在用面向对象语言编写程序的时候,依然会感觉自己在用面向过程的思维,笔者分享这篇文章的用意便是希望可以对大家有一些积极的影响. 阅读本文可以是没有接触设计模式,但需要一定的面向对象基础,至少简单理解封装,继承多态. 对于刚开始接触设计模式来说,一开始就说概念性的东西,很少能够理解.所以我们可以先跳过这些,通过一个小的程序场景来进行一个比较直观的认识. 模拟魂斗罗发射子&弹 相信大家小的时候玩过一款叫魂斗罗的游戏

浅谈设计模式3-模板方法模式

模版方法模式,个人认为还是用处比较多的一个设计模式,而且也是比较好学和理解的一个.依然来通过模拟一个场景来慢慢了解. 现在我们来实现一下泡茶这个过程.首先我们需要烧开一壶水,然后往茶壶中放茶叶,加入开水,等待茶泡好. 经过前两次的分享,大家应该具备了基本的面向对象的思想了,这里就不再用面向过程的方式演示了. 首先,有一种普通人,他泡茶的方式是这样的 public class Common     { public void MakeTea()         {             Heat

java设计模式之 装饰器模式

适AT java设计模式之 装饰器模式 装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构. 这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,动态给一个对象添提供了额外的功能. 我们通过下面的实例来演示装饰器模式的用法.模拟一个人从想吃饭.找饭店.享受美食.结束吃饭的过程 代码展示: 首先创建一个被修饰的接口 Eat package deco

浅谈设计模式的学习(下)

时间过得真快啊,不知不觉又要周末了,借这个周末时间.把<浅谈设计模式的学习(下)>补上吧. 在<浅谈设计模式的学习(中)>中,说到了保持抽象的思维.接下来说一下第四点,做一个分享,也记录一下自己的学习历程. 4.学习设计模式,就不要把它看的太认真    设计模式是一个编程思想,它不是具体的代码套路.举个例子说明一下: 由于家传,接触到了一些中国的传统武术.当我与那些不懂传统武术的人交流的时候,他们总是认为中国的传统武术都是些套路.花架子,只是用来好看.在他们认为,两人打架,别人出拳

浅谈设计模式的学习(上)

作为一个开发人员,能写出一个漂亮可扩展的代码,绝对是一件令人愉快的事情.那设计模式就是一门必修课! 本文就自己学习设计模式的一点经历做一个记录. 本人在读大学时,为了学习设计模式就买了一本<java与模式>的数据,书籍有一千多页很重.而且价格不菲.没办法,花那么多钱买的不看岂不浪费.于是每天早上读一章,坚持几个月我终于读完了.这几个月真是煎熬啊,几个月下来,回忆一下似乎自己真得也没收获到什么,很悍然啊.难道是书籍不好吗还是我读的不认真?其实在我现在看来都不是.而为什么读完了却什么也没收获到呢?

浅谈设计模式的学习(中)

在<浅谈设计模式的学习(上)>中我说到了设计模式的基石-----抽象思维.为什么需要抽象思维呢?因为越抽象就越不容易出错,就像有些领导人说话:坚持改革开放.但怎么算坚持改革开放呢,没有具体的标准,因事而异,所以就不容易违背这个坚持改革开放的原则了. 3.学习设计模式,要保持抽象的思维     什么是抽象思维呢?真的不好说,抽象的东西往往难以说明白,听了也难以搞明白,还是通过具体的例子来说吧 有这么一个学生请假的场景,如果请假时间一天以内则有班长批准就可以了,三天以内则需要老师批准,超过三天就得

浅谈DevExpress&lt;二&gt;:设计一个完整界面(1)

昨天谈了界面的换肤问题,今天拿一个简单的界面来介绍一下怎么设计一个五脏俱全的界面,总体效果如下图(种类的图片随便找的^^): 创建一个winform项目,在上面拉进去一个bar管理器和图片列表: 在菜单栏.工具栏和状态栏中,分别加入菜单.编辑栏.按钮和静态文本: 菜单栏改名并设置好图片: 然后改工具栏项的属性,拿第一个举个例子,后面的大同小异,选择EditItem后先将其PaintStyle属性改为CapationGlyph,然后找到Edit,选择CheckEdit,就会变成下面的样子: 依法炮

浅谈人们工作时存在的2种思维模式

工作的思维模式分2种:即时回报型和延时回报型. 即时回报型的表现:注重立刻见效的方式,比如刀钝了舍不得花时间磨,提刀急忙去砍柴:比如每天都大老远的去提水,而舍不得花时间和钱去修条水管:比如工作上遇到难题了,直接上网搜答案,而舍不得花时间从基础学起:比如执行某个软件操作时舍不得花时间去找快捷键,每次都从菜单里点. 相对的是延时回报式,表现为:刀钝了就先去磨刀,磨快了再去砍柴:修水管而不是去提水:学习先从基础的开始:注意使用快捷键. 表现远远不止这些.从表面上看,即时回报的方式短期见效快,长期效率差

浅谈DevExpress&lt;二&gt;:设计一个完整界面(2)

下面来把剩下的工作做完,换肤功能昨天已近讨论过,今天就不重复了.首先建立三个全局变量,一个存放文件路径,一个存放数据,一个存放过滤条件. string DBFileName; DataView dataView; string[] filter = new string[3]; 取得数据并绑定到表格中: DBFileName = DevExpress.Utils.FilesHelper.FindingFileName(Application.StartupPath, "Products.xml&