复合模式是HeadFirst上面详细讲的最后一个模式,其前面的模式作者认为都是成熟的经常使用的模式。所以这是详细讲解模式的最后一篇,同时这个模式讲解的篇幅也是最长的,接下来我就对其进行总结提炼进行讲解。复合模式顾名思义就是使用其他模式联合使用解决问题,但是将某些模式结合使用并不代表这些模式就能称为复合模式。复合模式必须够一般性,适合解决许多问题。相信我们大家都知道的MVC就是复合模式的应用,那么我们就来看模式如何结合使用和MVC中使用到的模式。

模式结合

  记得第一个模式,策略模式就是以鸭子开头,而最后一个模式用鸭子结尾,做到首尾呼应吧。我们依然看鸭子的例子来讲解我们的复合模式。

  (1)首先创建一个Quackable,然后让某些鸭子实现接口。

     public interface Quackable
{
public void Quack();
} public class RedheadDuck : Quackable
{
public void Quack()
{
Console.WriteLine("呱呱呱");
}
}

  (2)我们写了一个红头鸭的类,然后我们再加点其他种类的鸭子,例如橡皮鸭。

     public class RubberDuck : Quackable
{
public void Quack()
{
//橡皮鸭的叫声
Console.WriteLine("吱吱吱");
}
}

  (3)测试一下写的例子,测试代码

  (4)当我们有鸭子的时候,我们也许有一只鹅。

     public class Goose
{
public void Honk() {
Console.WriteLine("咯咯咯");
}
}

  (5)如果我们要把鹅也加入到模拟器中,那么为了统一处理我们可以使用适配器将鹅适配成鸭子

     public class GooseAdapter : Quackable
{
private Goose goose;
public GooseAdapter(Goose goose) {
this.goose = goose;
}
public void Quack()
{
goose.Honk();
}
}

  (6)当我们适配成鸭子后在模拟器中加入鹅

   (7)如果我们要知道叫声的次数我们需要一个装饰者,通过把鸭子包装进装饰者对象,给鸭子一些新行为(计算次数的行为)。我们不用修改鸭子的代码。

     public class QuackCounter : Quackable
{
Quackable duck;
private static int numberOfQuacks;
public QuackCounter(Quackable duck)
{
this.duck = duck;
} public void Quack()
{
duck.Quack();
numberOfQuacks++;
} public static int GetQuacks()
{
return numberOfQuacks;
}
}

  (8)包装实例化Quackable,统计叫声次数。

  (9)对于装饰和没被装饰的鸭子我们想分别管理,让创建的和装饰部分包装起来。我们需要创建一个工厂,而且是不同类型鸭子的产品家族,所以我们要用抽象工厂模式。

     /// <summary>
/// 定义抽象工厂,由子类创建不同的家族
/// </summary>
public abstract class AbstractDuckFactory
{
public abstract Quackable CreateReadheadDuck();
public abstract Quackable CreateRubberDuck();
} /// <summary>
/// 没有装饰者的工厂
/// </summary>
public class DuckFactory : AbstractDuckFactory
{
public override Quackable CreateReadheadDuck()
{
return new RedheadDuck();
} public override Quackable CreateRubberDuck()
{
return new RubberDuck();
}
} /// <summary>
/// 有装饰者的工厂
/// </summary>
public class CountingDuckFactory : AbstractDuckFactory
{
public override Quackable CreateReadheadDuck()
{
return new QuackCounter(new RedheadDuck());
} public override Quackable CreateRubberDuck()
{
return new QuackCounter(new RubberDuck());
}
}

  (10)使用工厂模式

  (11)有了工厂模式统一创建鸭子,我们还可以统一管理鸭子,而组合模式允许我们像对待单个对象一样对待对象集合。组合需要和叶节点元素一样实现相同的接口,这里的叶节点就是Quackable。

     public class Flock : Quackable
{
private List<Quackable> quackables = new List<Quackable>(); public void Add(Quackable quackable) {
quackables.Add(quackable);
}
public void Quack()
{
var enumerator= quackables.GetEnumerator();
while (enumerator.MoveNext()) {
Quackable quackable = enumerator.Current;
quackable.Quack(); }
}
}

  (12)在这个组合模式中我们遍历鸭子的叫声的时候用到了foreach循环的本质方法,这里实际是另外一个迭代器模式。

  然后我们改造一下测试模拟器,看看输出结果。

 (13)最后我们还整合一个需求,当有人想要观察鸭子的行为,我们可以给鸭子加上一个观察者模式。

  观察者需要一个Observable接口,所谓的Observable就是被观察的对象。Observable需要注册和通知观察者的方法。

     public interface QuackObservable
{
public void RegisterObserver(Observer observer);
public void NotifyObservers();
}

  鸭子要实现接口QuackObservable,由于鸭子都实现了Quackable接口,所以我们可以让Quackable实现QuackObservable接口。

     public interface Quackable:QuackObservable
{
public void Quack();
}

  (14)我们需要在鸭子的每个类中实现注册和通知,但是这里我们可以新建一个类Observable用来封装注册和通知的代码,然后将他和QuackObservable组合在一起,这样我们只需要一份注册和通知的代码,QuackObservable所有的调用都委托给Observable这个辅助类。

     public class Observable : QuackObservable
{
//观察者
List<Observer> observers = new List<Observer>();
QuackObservable duck; public Observable(QuackObservable duck) {
this.duck = duck;
} public void RegisterObserver(Observer observer)
{
observers.Add(observer);
} public void NotifyObservers()
{
foreach (var observer in observers)
{
observer.Update(duck);
}
}
}

  (15)然后我们以红头鸭为例改造被观察者,整合Quackable类和Observable。

     public class RedheadDuck : Quackable
{
Observable observable;
public RedheadDuck() {
observable = new Observable(this);
}
public void RegisterObserver(Observer observer)
{
observable.RegisterObserver(observer);
} public void NotifyObservers()
{
observable.NotifyObservers();
} public void Quack()
{
Console.WriteLine("呱呱呱");
NotifyObservers();
}
}

  (16)如果是一群鸭子观察,则我们修改Flock类,注册时候注册到每个要观察的叶节点上,然后当通知的时候各自叶节点会调用自己的NotifyObservers,所有Flock的NotifyObservers就不用做任何事情。

     public class Flock : Quackable
{
private List<Quackable> quackables = new List<Quackable>(); public void Add(Quackable quackable)
{
quackables.Add(quackable);
} public void Quack()
{
var enumerator = quackables.GetEnumerator();
while (enumerator.MoveNext())
{
Quackable quackable = enumerator.Current;
quackable.Quack();
}
} public void RegisterObserver(Observer observer)
{
foreach (var duck in quackables)
{
duck.RegisterObserver(observer);
}
} public void NotifyObservers(){}
}

  (17)现在完成Observer端。

     public interface Observer
{
void Update(QuackObservable duck);
} public class QuackObserver : Observer
{
public void Update(QuackObservable duck)
{
Console.WriteLine("观察者:"+duck+" 正在叫");
}
}

  (18)加入观察者测试。

  通过这个例子我们组合了6个设计模式,你可能要问这就是复合模式?不,这只是一群模式携手合作。所谓的复合模式,是指一群模式被结合起来使用,以解决一般性问题。而这个例子只是为了演示如何将模式结合起来,但它不是为了解决一般性问题。

  结合上面的代码我们画一个类图便于理解例子中模式如何协作结合的。

复合模式:结合两个或以上的模式,组成一个解决方案,解决以再发生的一般性问题。

MVC复合模式

M:model模型,模型持有所有的数据、状态和程序逻辑。

V:visual视图,用来呈现状态和数据,是和用户交互的界面。

C:control控制,取得用户的输入并告知模型如何作出对应的动作。

MVC包含的设计模式

策略模式:视图通过控制器对模型进行修改,视图是一个对象,可以被调整为使用不同的控制器(不同策略)。

组合模式:界面中的每个显示组件不是组合节点就是叶节点。当控制器想要做某种更新时,只需告诉视图最顶层的组件即可,组合模式会处理组合节点或叶节点的更新。

观察模式:当模型发生改变时,需要立即反馈到视图中,此时可以把控制器或视图作为观察者,观测模型的动态变化。这样模型完全独立于视图和控制器,是一个松耦合的实现。
虽然MVC中的设计模式也许不再试经典意义上的模型,但现实中设计模式都不一定照搬经典设计,会有优化或改动,所以并不影响它就是设计模式的使用。

这就是复合模式的概念和例子,HeadFirst中的所有细讲模式都已经结束,下一次我会罗列其他没有详细讲解的设计模概念,也许在其他地方使用到了我会回来补全例子和代码。

Head First设计模式——复合模式的更多相关文章

  1. java设计模式----复合模式

    复合模式:复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题 要点: 1.MVC是复合模式,结合了观察者模式.策略模式和组合模式 2.模型使用观察者模式,以便观察者更新,同时保持 ...

  2. 《Head First 设计模式》学习笔记——复合模式

    模型-视图-控制器(MVC模式)是一种很经典的软件架构模式.在UI框架和UI设计思路中扮演着很重要的角色.从设计模式的角度来看,MVC模式是一种复合模式.它将多个设计模式在一种解决方式中结合起来,用来 ...

  3. 设计模式学习--复合模式(Compound Pattern)

    设计模式学习--复合模式(Compound Pattern) 概述 ——————————————————————————————————————————————————— 2013年8月4日<H ...

  4. 设计模式之复合模式(Compound Pattern)

    一.什么是复合模式? 在形式上,复合模式确实是多个模式的组合,但满足了这一条并不一定是复合模式,注意它的定义: 将多个模式结合起来形成一个“框架”,以解决一般性问题 一提到“框架”,可能最容易联想到的 ...

  5. 【HeadFirst设计模式】12.复合模式

    定义: 复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题. 要点: MVC模式是复合模式,结合了观察者模式.策略模式和组合模式. 模型使用了观察者模式,以便观察者更新,同时保存 ...

  6. Java 设计模式_复合模式(2016-08-31)

    一.什么是复合模式? 在形式上,复合模式确实是多个模式的组合,但满足了这一条并不一定是复合模式,注意它的定义: 将多个模式结合起来形成一个“框架”,以解决一般性问题 一提到“框架”,可能最容易联想到的 ...

  7. .NET设计模式访问者模式

    一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...

  8. linkin大话设计模式--常用模式总结

    linkin大话设计模式--常用模式总结 一,常用设计模式定义 Abstract Factory(抽象工厂模式):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. Adapter( ...

  9. [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

随机推荐

  1. Dangal 观影感受,(摘录)

    ===================================================================================== 引用: https://ww ...

  2. 实战_3:新建产品配置(product)并导出项目

    产品配置Product 产品配置用于定义和管理RCP应用的多个方面特征.并支持将RCP项目导出为部署包(类似eclipse压缩包),可以直接部署到其他环境上使用. 产品配置必须新建一个 扩展名为 .p ...

  3. OpenCV 图像平滑处理

    #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" us ...

  4. 浏览器证书问题,chorm,ie,edge,safari都会去读系统证书,firefox例外

    坑爹 没想过浏览器兼容的问题. 为系统安装用户证书后, firefox一直无法连接 提示 连接 www.httpsserver.com:8985 时发生错误. SSL 对等端无法协商出一个可接受的安全 ...

  5. HDU-1711-Number Sequence(KMP)(Rabin-Karp)

    Rabin-Karp Accepted 1711 904MS 5272K 1310 B G++ #include "bits/stdc++.h" using namespace s ...

  6. 地理位置(Geolocation)API 简介

    一.开篇简述 Geolocation API(地理位置应用程序接口)提供了一个可以准确知道浏览器用户当前位置的方法.且目前看来浏览器的支持情况还算不错(因为新版本的IE支持了该API),这使得在不久之 ...

  7. <USACO09FEB>庙会捷运Fair Shuttleの思路

    一个没有被我成功证明的 贪心 但是 ac了的 别人排序都是排终点.但我的排终点错了emm排起点才对qvq 有没有人友情看看怎么证(没有 #include<cstdio> #include& ...

  8. 维生素D补充过多会中毒

    虽然我们的物质生活越来越丰富,各种食材几乎一年四季都能够吃到,然而却越来越多的人选择进行补充各种维生素,但是你知道吗?维生素不是我们想象中多吃无害的,补充过多也会要人命,特别是最近非常流行补充的一种维 ...

  9. cookie存在哪里???

    平时各位在做项目时多半时候都会用到客户端的cookie,可大家知道cookie是存储在哪里吗? 首先cookie失效分为2种: 1:设置过期时间失效(只要设置了过期时间cookie就会存储在硬盘里面) ...

  10. nginx 代理第三方邮件站点

    需求:公司业务服务器使用的是阿里云,要求内网(仅有内网IP)所有流量走网关服务器(有外网IP及内网IP),内网服务器需要调用一个公网上的第三方邮件站点.在参考了https://www.linuxba. ...