读书笔记-大话设计模式

迪米特法则

  • 也叫最少知识原则,即:类的设计要降低耦合,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用

  • 在类的结构设计上,每一个类都应当尽量降低成员的访问权限,设计时应当考虑两个类是直接发生调用关系,还是通过第三方来搭建关系

合成/聚合复用原则

  • 尽量使用合成/聚合,尽量不要使用类继承,因为父类的改变,会影响到所有子类

  • 聚合表示一种弱的拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。合成是一种强的拥有关系,体现的是严格的部分和整体的关系。

  • 大雁拥有翅膀(合成),许多大雁聚合成雁群(聚合)


原型模式

  • 深复制:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象

  • 浅复制:被复制对象的鄋变量都含有与原来的对象相同的值,而所有对其他对象的引用都仍然指向原来的对象

  • 如何实现深复制: 用 私有构造函数 创建引用对象,然后再clone方法里调用私有构造函数,完成克隆,其他的值引用则在clone里面直接赋值就好了

模板模式

  • 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法是的子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

  • 一切逻辑都在父类中写好,需要延迟交给子类的部分,通过让子类@Override方法来实现,或者抽象类实现逻辑,具体类实现细节

外观模式

  • 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用,比如,基金是各种股票的外观模式,购买者只需要和基金打交道就好了

  • 分层的处理:Facade类,承上启下的作用,对外暴露的接口简单,统一

建造者模式

  • Builder 和 Director: Builder是抽象类,用于让开发者实现一些细节步骤,Director里面包含了Buider的实例,用于封装一些操作逻辑,这样开发者每次只需要根据自己的需求实现Builder,然后交给Director就可以了,不用care操作逻辑是否有遗漏

  • 适用于当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时适用的模式,即将一个复杂对象的构建与它的表示分离,使得同样的构建过程(Director)可以创建不同的表示(Builder)

状态模式

  • 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类

  • 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时,把状态的判断逻辑转移到表示不同状态的一系列类当中(实际!

适配器模式

  • 将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

  • 使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式,即:使用一个Adapter类实现抽象接口,里面持有待适配的对象,在Override接口方法的时候,将待适配对象的方法实现到接口中

备忘录模式

  • 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

  • Originator(发起人,负责创建一个备忘录,即在SaveStatus时创建个Mememto) 和 Memento(备忘录,负责创建状态副本,保存在自己的类中) 和 Caretaker(管理者,负责管理内部的状态副本get和set)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Originator {

public Mememto SaveState(){
return new Memento(vit,atk,def)
}
public void RecoveryState(Mememto state){
this.vit = state.vit;
this.atk = state.atk;
this.def = state.def;
}
}

class Memento {

private int vit;
private int atk;
private int def;
public Memento(int vit, int atk, int def){
this.vit = vit;
this.atk = atk;
this.def = def;
}
/...
get/set
.../
}

class Caretaker {
private Memento memento;
/...
get/set
.../
}

//----------To Do----------

Caretaker.memento = Originator.SaveState();
Originator.RecoveryState(Caretaker.memento);

组合模式

  • 将对象组合成属性结构以表示”部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性

  • “部分-整体” 的关系实质上为 “树叶-根”的关系,所有的组件实现统一的接口,这个接口包含扩展组件的能力,即

1
2
3
4
5
6
7
8
9
10
11
12
abstarct class Component{

protected string name;

public Component(string name){
this.name = name;
}

public abstarct void Add(Compoent c); // 扩展能力
public abstarct void Remove(Compoent c); // 扩展能力
public abstarct void Display(Compoent c); // 各司其职
}

迭代器模式

  • 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示,即当你需要访问一个聚集对象,而且不管这些对象是什么,就应该考虑用迭代器模式

  • 迭代器抽象类(Iterator) 和 迭代器具体类 (ConcreteIterator)

  • 聚集抽象类(Aggregate)和 聚集具体类(ConcreteAggregate)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
abstaract class Iterator {

public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}

abstaract class Aggregate {
public abstract Iterator createIterator();
}

class ConcreteAggregate:Aggregate {

private IList<object> items = new List<object>();
public orerride Iterator createIterator{
return new ConcreteIterator(this);
}
}

class ConcreteIterator : Iterator {

private ConcreteAggregate aggregate;
public ConcreteIterator(ConcreteAggregate aggregate){
this.aggregate = aggregate;
}
/**
* Override methods in Iterator
* /
}

桥接模式

  • 将抽象部分与它的实现部分分离,使它们都可以独立的变化

  • Abstraction 和 Implementor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
abstract class Implementor {
public abstarct void Operation();
}

class ConcreteImplementorA : Implenmentor{
public override void Operation()
}

class ConcreteImplementorB : Implenmentor{
public override void Operation()
}

class Abstraction {
protected Implementor implementor;
public void SetImplementor(Implementor implementor){
this.implementor = implementor;
}
public virtual void Operation(){}
}

class RefinedAbstraction: Abstraction{
public override void Operation(){
implementor.Operation();
}
}

static void Main(string[] args){
Abstraction ab = new RefinedAbstraction();
ab.SetImpelementor(new ConcreteImplementorA());
ad.Operation();
ab.SetImpelementor(new ConcreteImplementorB());
ad.Operation();
}

命令模式

  • 分离两个类的职责,统一规划到中间的消息队列管理:客户 - 服务员 - 烤肉者

  • 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作,它将请求一个操作的对象与知道怎么执行一个操作的对象分隔开: Command 和 Receiver 绑定,而 Command 的调度执行,由 Invoker 负责

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
abstract class Command{

protected Receiver receiver;
public Command(Receiver receiver){
this.receiver = receiver;
}
abstract public void Execute();
}

class ConcreteCommand : Command{

public ConcreteCommand(Receiver receiver): base(receiver){}
public override void Execute(){
receiver.Action();
}
}

class Invoker{

private Command command;
public void SetCommand(Command command){
this.command = command;
}
public void ExecuteCommand(){
command.Execute();
}
}

class Receiver{
public void Action(){}
}

public static void Main(){
Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(c);
i.ExecuteCommand();
}

职责链模式

  • 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这个对象连成一个链,并沿着这条链传递该请求,知道有一个对象处理它为止(Chain)

  • 接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,仅需要保持一个向后引用

  • 随时增加或修改处理一个请求的结构,增强了给对象指派职责的灵活性,最坏情况:到末端都得不到处理,需要事先考虑全面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class Handler{

protected Handler successor;
public void SetSuccessor(Handler successor){
this.successor = successor;
}
public abstract void HandleRequest(int request);
}

class ConcreteHandler1 : Handler {
public override void HandleRequest(int request){
if(request >= 0 && request < 10){
// do handle request
}else if(successor != null){
successor.HandleRequest(request);
}
}
}

中介模式

  • 对象之间大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整理,所谓低耦合的解决方案:中介模式其中之一

  • 用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显示地相互引用,从而使其耦合松散,并且可以独立的改变他们之间的交互。

  • 缺点:把交互的复杂性变成了中介者的复杂性,需要着重考虑,对象之间多对多的交互,首先应当考虑系统设计上的合理性

享元模式

  • 如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用享元模式,还有就是对象的大多数的外部状态,如果删除不影响的话,那么可以用相对较少的共享对象取代很多组对象,此时也应该考虑使用享元模式,比如:线程池

  • 享元模式共享的是对象,对象数量是有限制的,因此会在工厂内部保存对象的引用,而工厂模式是生成对象,对象数量是无限制的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
abstract class Flyweight{
public abstract void Operation(int ee)
}

class ConcreteFlyweight : Flyweight{
public override void Operation(int ee){}
}

class FlyweightFactory{

private Hashtable flyweights = new Hashtable();

public FlyweightFactory(){
//内部保留有限的对象数
flyweights.Add("X", new ConcreteFlyweight());
flyweights.Add("Y", new ConcreteFlyweight());
flyweights.Add("Z", new ConcreteFlyweight());
}

public Flyweight GetFlyweight(string key){
return ((Flyweight)flyweights[key]);
}
}

解释器模式

  • 同样的一个抽象操作,需要不同的实施方法,则考虑解释器模式

  • 缺点在于需要维护多个解释器实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
abstract class AbstractExpression {
public abstract void Interpret(Context ctx)
}

TerminalExpression: AbstractExpression {
public override void Interpret(Context ctx){}
}

NonterminalExpression: AbstractExpression {
public override void Interpret(Context ctx){}
}

// 全局信息
class Context {

private string input;
private string output;
}

static void Main(string[] args){
Context ctx = new Context();
AbstractExpression terminal = new TerminalExpression();
terminal.interpret(ctx);
AbstractExpression terminal = new NonterminalExpression();
nonterminal.interpret(ctx);
}

访问者模式

  • 表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类前提下定义作用于这些元素的新操作。

  • 访问者模式的目的是要把处理从数据结构分离出来,有稳定的数据结构,又有易于变化的算法,使用访问者模式就是比较合理的,因为增加算法的操作变得尤为容易

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
abstract class Visitor {
public abstract void useAlgorithmA(concreteElementA A);
public abstract void useAlgorithmB(concreteElementB B)
}

ConcreteVisitor1: Visitor {
// implements
}

ConcreteVisitor2: Visitor {
// implements
}

abstract class Element{
public abstract void Accept(Visitor visitor);
}

ConcreteElementr1 : Element {
public override void Accept(Visitor visitor){
visitor.useAlgorithmA(this);
}
}

ConcreteElementr2 : Element {
public override void Accept(Visitor visitor){
visitor.useAlgorithmB(this);
}
}

class Contorller {
//整合 visitor 和 element, 使得对外操作统一
private IList<Element> elements = new List<Element>();

public void Attach(Element element){
elements.Add(element);
}

public void Detach(Element element){
elements.Remove(element);
}

public void Accept(Visitor visitor){
foreach(Element e in elements){
e.Accept(visitor);
}
}
}
如需转载,请注明出处