Head First设计模式——复合模式
复合模式是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设计模式——复合模式的更多相关文章
- java设计模式----复合模式
复合模式:复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题 要点: 1.MVC是复合模式,结合了观察者模式.策略模式和组合模式 2.模型使用观察者模式,以便观察者更新,同时保持 ...
- 《Head First 设计模式》学习笔记——复合模式
模型-视图-控制器(MVC模式)是一种很经典的软件架构模式.在UI框架和UI设计思路中扮演着很重要的角色.从设计模式的角度来看,MVC模式是一种复合模式.它将多个设计模式在一种解决方式中结合起来,用来 ...
- 设计模式学习--复合模式(Compound Pattern)
设计模式学习--复合模式(Compound Pattern) 概述 ——————————————————————————————————————————————————— 2013年8月4日<H ...
- 设计模式之复合模式(Compound Pattern)
一.什么是复合模式? 在形式上,复合模式确实是多个模式的组合,但满足了这一条并不一定是复合模式,注意它的定义: 将多个模式结合起来形成一个“框架”,以解决一般性问题 一提到“框架”,可能最容易联想到的 ...
- 【HeadFirst设计模式】12.复合模式
定义: 复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题. 要点: MVC模式是复合模式,结合了观察者模式.策略模式和组合模式. 模型使用了观察者模式,以便观察者更新,同时保存 ...
- Java 设计模式_复合模式(2016-08-31)
一.什么是复合模式? 在形式上,复合模式确实是多个模式的组合,但满足了这一条并不一定是复合模式,注意它的定义: 将多个模式结合起来形成一个“框架”,以解决一般性问题 一提到“框架”,可能最容易联想到的 ...
- .NET设计模式访问者模式
一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...
- linkin大话设计模式--常用模式总结
linkin大话设计模式--常用模式总结 一,常用设计模式定义 Abstract Factory(抽象工厂模式):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. Adapter( ...
- [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
随机推荐
- IDEA Maven项目中添加tomcat没有无artifact选项
IntelliJ使用 ##使用IntelliJ IDEA配置web项目时,选择Edit Configration部署Tomcat的Deployment可能会出现以下情况: 导致新手部署过程中摸不着头脑 ...
- 【转】HeadFirst 组合模式+迭代器错误原因以及解决代码
http://blog.csdn.net/sugar_girl/article/details/53400267 <HeadFirst JAVA设计模式>中用迭代器迭代组合模式是存 ...
- MRP执行计划列表(禁用)
1.最直接的方法,推进方法 2.比较麻烦的方法
- ofo小黄车推出车身商业化广告,能自救成功吗?
ofo终于还是扛不住了!作为之前与摩拜相抗衡的巨头,ofo其实也是最被看好的共享单车企业之一.可惜共享单车行业的窘境,终究不是成为巨头后就能拯救的.摩拜被美团收购后,ofo就成为巨头垂涎的目标.数十亿 ...
- sm1、sm2、sm3、sm4简单介绍
转自:https://blog.csdn.net/andylau00j/article/details/54427395 国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥 ...
- echo追加和覆盖
追加: echo " " >> 文件名 覆盖: echo " " > 文件名
- Android开发之《USB Camera》
SimpleWebCam Source Code:https://bitbucket.org/neuralassembly/simplewebcam/src 1. USB摄像头UVC兼容(如今大部分兼 ...
- jdk源码理解-String类
String类的理解 简记录一下对于jdk的学习,做一下记录,会持续补充,不断学习,加油 1.String的hash值的计算方法. hash值的计算方法多种多样,jdk中String的计算方法如下,比 ...
- Windows server 2008 r2下安装sqlserver2012
在微软官网上下载sqlserver2012镜像文件:用Alcohol 120%软件进行驱动安装. 如果C盘的容量不够的话,上边的路径可以修改
- 吴裕雄--天生自然 python开发学习笔记:下载python离线安装whl文件链接
https://www.lfd.uci.edu/~gohlke/pythonlibs/