第1部分 适应设计模式
第1章 Iterator(迭代器) 模式-一个一个遍历 (已看)
第2章 Adapter(适配器) 模式-加个"适配器"模式以便于复用 (已看)
第2部分 交给子类
第3章 Template Method(模板方法) 模式-将具体处理交给子类 (已看)
第4章 Factory Method(工厂方法) 模式-将实例的生成交给子类 (已看)
第3部分 生成实例
第5章 Singleton(单例) 模式-只有一个实例 (已看)
第6章 Prototype(原型) 模式-通过复制生成实例 (已看)
第7章 Builder(建造者) 模式-组装复杂的实例 (已看)
第8章 Abstract Factory(抽象工厂) 模式-将关联零件组装成产品 (已看)
第4部分 分开考虑
第9章 Brige(桥接) 模式-将类的功能层次结构与实现层次结构分离 (已看)
第10章 Strategy(策略) 模式-整体地替换算法 (已看)
第5部分 一致性
第11章 Composite(组合) 模式-容器与内容的一致性 (已看)
第12章 Decorator(装饰) 模式-装饰边框与被装饰物的一致性 (已看)
第6部分 访问数据结构
第13章 Visitor(访问者) 模式-访问数据结构并处理数据 (已看)
第14章 Chain of Responsibility(职责链) 模式-推卸责任 (已看)
第7部分 简单化
第16章 Mediator(中介者) 模式-只有一个仲裁者 (已看)
第8部分 管理状态
第17章 Observer(观察者) 模式-发送状态变化通知 (已看)
第18章 Memento(备忘录) 模式-保存对象状态 (已看)
第9部分 避免浪费
第20章 Flyweight(享元) 模式-共享对象,避免浪费 (已看)
第21章 Proxy(代理) 模式-只在必要时生成实例 (已看)
第10部分 用类来表现
第22章 Command(命令) 模式-命令也是类 (已看)
第23章 Interpreter(解释器) 模式-语法规则也是类 (已看)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
第1部分 适应设计模式
第1章 Iterator(迭代器) 模式-一个一个遍历
using System; using System.Collections; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { BookShelf bookShelf = new BookShelf(3); Book book1 = new Book("Book1"); Book book2 = new Book("Book2"); Book book3 = new Book("Book3"); bookShelf.AddBook(book1); bookShelf.AddBook(book2); bookShelf.AddBook(book3); IIterator iterator = bookShelf.iterator(); while (iterator.hasNext()) { Book book = iterator.next() as Book; Console.WriteLine(book.getName()); } } } public interface IAggregate { IIterator iterator(); } public interface IIterator { bool hasNext(); object next(); } public class BookShelf : IAggregate { private Book[] books; private IIterator iter; private int length; public BookShelf(int maxSize) { books = new Book[maxSize]; length = 0; } public int getLength() { return length; } public Book getBookAt(int index) { return books[index]; } public void AddBook(Book book) { books[length] = book; length++; } public IIterator iterator() { return new BookShelfIterator(this); } } public class BookShelfIterator : IIterator { private BookShelf bookShelf; private int pos; public BookShelfIterator(BookShelf bookShelf) { this.bookShelf = bookShelf; pos = 0; } public bool hasNext() { if (pos < bookShelf.getLength()) { return true; } else { return false; } } public object next() { Book book = bookShelf.getBookAt(pos); pos++; return book; } } public class Book { private string name; public Book(string name) { this.name = name; } public string getName() { return name; } } }
Iterator模式的类图
相关模式
Vistor模式
Iterator模式是从集合中一个一个取出元素进行遍历,但是并没有在Iterator接口中声明对取出的元素进行何种处理
Visitro模式则是在遍历元素集合的过程中,对元素进行相同的处理
在遍历集合的过程中对元素进行固定的处理是常有的需求.Visitor模式正是为了应对这种需求而出现的.
在访问元素集合的过程中对元素进行相同的处理.这种模式就是Visitor模式
Composite模式
Composite模式是具有递归结构的模式,在其中使用Iterator模式比较困难
Factory Method模式
在iterator方法中生成的Iterator的实例可能会使用Factory Method模式
第2章 Adapter(适配器) 模式-加个"适配器"模式以便于复用
using System; using System.Collections; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { IPrint banner = new PrintBanner("haha"); banner.printWeak(); banner.printStrong(); } } public class Banner { private string str; public Banner(string str) { this.str = str; } public void showWithParen() { Console.WriteLine("(" + str + ")"); } public void showWithAster() { Console.WriteLine("*" + str + "*"); } } public interface IPrint { void printWeak(); void printStrong(); } public class PrintBanner : Banner,IPrint { public PrintBanner(string str) : base(str) { } public void printWeak() { base.showWithParen(); } public void printStrong() { base.showWithAster(); } } }
类适配器模式的类图(使用继承)
using System; using System.Collections; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { APrint print = new PrintBanner(new Banner("Hello")); print.printWeak(); print.printStrong(); } } public abstract class APrint { public abstract void printWeak(); public abstract void printStrong(); } public class PrintBanner : APrint { private Banner banner; public PrintBanner(Banner banner) { this.banner = banner; } public override void printWeak() { banner.showWithParen(); } public override void printStrong() { banner.showWithAster(); } } public class Banner { private string str; public Banner(string str) { this.str = str; } public void showWithParen() { Console.WriteLine("(" + str + ")"); } public void showWithAster() { Console.WriteLine("*" + str + "*"); } } }
类适配器模式的类图(使用继承)
相关的设计模式
Bridge模式
Adapter模式用于连接接口(API)不同的类,而Bridge模式则用于连接类的功能层次结构与实现层次结构
Decorator模式
Adapter模式用于填补不同接口(API)之间的缝隙,而Decorator模式则是在不改变接口(API)的前提下增加功能
第2部分 交给子类
第3章 Template Method(模板方法) 模式-将具体处理交给子类
using System; namespace Test1 { class Program { static void Main(string[] args) { AbstractDisplay d1 = new CharDisplay('H'); AbstractDisplay d2 = new StringDisplay("Hello,World."); AbstractDisplay d3 = new StringDisplay("World,Hello"); d1.display(); d2.display(); d3.display(); } } public abstract class AbstractDisplay { public abstract void open(); public abstract void print(); public abstract void close(); public void display() { open(); for (int i = 0; i < 5; i++) { print(); } close(); } } public class CharDisplay : AbstractDisplay { private char ch; public CharDisplay(char ch) { this.ch = ch; } public override void open() { Console.WriteLine("<<"); } public override void print() { Console.WriteLine(ch); } public override void close() { Console.WriteLine(">>"); } } public class StringDisplay : AbstractDisplay { private string str; private int width; public StringDisplay(string str) { this.str = str; this.width = str.ToCharArray().Length; } public override void open() { printLine(); } public override void print() { Console.WriteLine("|" + str + "|"); } public override void close() { printLine(); } private void printLine() { Console.Write("+"); for (int i = 0; i < width; i++) { Console.Write("-"); } Console.WriteLine("+"); } } }
Template Method模式的类图
相关的设计模式
Factory Method模式
Factory Method模式是将Template Method模式用于生成实例的一个典型例子
Strategy 模式
在Template Method模式中,可以使用继承改变程序的行为.这是因为Template Method模式在父类中定义程序行为的框架,在子类中决定具体的处理.
与此相对的是Strategy模式,它可以使用委托改变程序的行为.与Template Method模式中改变部分程序行为不同的是,Strategy模式用于替换整个算法.
延伸阅读:类的层次与抽象类
父类对子类的要求
我们在理解类的层次时,通常是站在子类的角度进行思考的.也就是说,很容易着眼于以下几点
在子类中可以使用父类中定义的方法
可以通过在子类中增加方法增加方法以实现新的功能
在子类中重写父类的方法可以改变程序的行为
现在,让我们稍微改变一下立场,站在父类的角度进行思考.在父类中,我们声明了抽象方法,而将该方法的实现交给了子类.换言之,就程序而言,声明抽象方法是希望达到以下目的.
期待子类去实现抽象方法
要求子类去实现抽象方法
也就是说,子类具有实现在父类中所声明的抽象方法的责任.因此,这种责任被称为"子类责任"(subclass responsibility).
第4章 Factory Method(工厂方法) 模式-将实例的生成交给子类
using System; using System.Buffers; using System.Collections; using System.Collections.Generic; namespace Test1 { class Program { static void Main(string[] args) { AFactory factory = new IDCardFactory(); AProduct card1 = factory.create("小明"); AProduct card2 = factory.create("小红"); AProduct card3 = factory.create("小刚"); card1.use(); card2.use(); card3.use(); } } public abstract class AProduct { public abstract void use(); } public abstract class AFactory { public AProduct create(string owner) { AProduct p = createProduct(owner); registerProduct(p); return p; } protected abstract AProduct createProduct(string owner); protected abstract void registerProduct(AProduct product); } public class IDCard : AProduct { private string owner; public IDCard(string owner) { this.owner = owner; Console.WriteLine("制作" + owner + "的ID卡."); } public override void use() { Console.WriteLine("使用" + owner + "的ID卡"); } public string getOwner() { return owner; } } public class IDCardFactory : AFactory { private ArrayList owners = new ArrayList(); protected override AProduct createProduct(string owner) { return new IDCard(owner); } protected override void registerProduct(AProduct product) { owners.Add(((IDCard) product).getOwner()); } public ArrayList getOwners() { return owners; } } }
Factory Method模式的类图
相关的设计模式
Template Method模式
Factory Method模式是Template Method的典型应用
Singleton模式
在多数情况下我们可以将Singleton模式用于扮演Creator角色(或是ConcreteCreator角色)的类
这是因为在程序中没有必要存在多个Crerator角色(或是ConcreteCreator角色)的实例
Composite模式
有时可以将Composite模式用于Product角色(或是ConreteProduct角色).
Iterator模式
有时,在Iterator模式中使用iterator方法生成Iterator的实例时会使用Factory Method模式.
第3部分 生成实例
第5章 Singleton(单例) 模式-只有一个实例
using System; namespace Test1 { class Program { static void Main(string[] args) { Console.WriteLine("Start."); Singleton obj1 = Singleton.getInstance(); Singleton obj2 = Singleton.getInstance(); if (obj1 == obj2) { Console.WriteLine("obj1与obj2是相同的实例"); } else { Console.WriteLine("obj1与obj2是不同的实例"); } } } public class Singleton { private static Singleton singleton = new Singleton(); private Singleton() { Console.WriteLine("生成了一个实例"); } public static Singleton getInstance() { return singleton; } } }
Singleton模式的类图
相关的设计模式
AbstractFactory 模式
Builder 模式
Facade 模式
Prototype 模式
第6章 Prototype(原型) 模式-通过复制生成实例
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; namespace ConsoleApplication1 { public class Program { public static void Main(string[] args) { Manager manager = new Manager(); UnderlinePen upen = new UnderlinePen('~'); MessageBox mBox = new MessageBox('*'); MessageBox sBox = new MessageBox('/'); manager.register("strong message",upen); manager.register("warning box",mBox); manager.register("slash box",sBox); IProduct p1 = manager.create("strong message"); p1.use("Hello,world."); IProduct p2 = manager.create("warning box"); p2.use("Hello,world."); IProduct p3 = manager.create("slash box"); p3.use("Hello,world."); } } public interface IProduct : ICloneable { void use(string str); IProduct createClone(); } public class MessageBox : IProduct { private char decoChar; public MessageBox(char deoChar) { this.decoChar = deoChar; } public void use(string str) { int length = str.ToCharArray().Length; for (int i = 0; i < length + 4; i++) { Console.Write(decoChar); } Console.WriteLine(""); Console.WriteLine(decoChar + " " + str + " " + decoChar); for (int i = 0; i < length + 4; i++) { Console.Write(decoChar); } Console.WriteLine(""); } public IProduct createClone() { return (IProduct) MemberwiseClone(); } public Object Clone() { return MemberwiseClone(); } } public class UnderlinePen : IProduct { private char ulChar; public UnderlinePen(char ulChar) { this.ulChar = ulChar; } public void use(string str) { int length = str.ToCharArray().Length; Console.WriteLine("\"" + str + "\""); Console.Write(" "); for (int i = 0; i < length; i++) { Console.Write(ulChar); } Console.WriteLine(""); } public IProduct createClone() { return (IProduct)MemberwiseClone(); } public Object Clone() { return MemberwiseClone(); } } public class Manager { private Dictionary<string,IProduct> showcase = new Dictionary<string, IProduct>(); public void register(string name, IProduct proto) { showcase.Add(name,proto); } public IProduct create(string protoName) { IProduct product = (IProduct) showcase[protoName]; return product.createClone(); } } }
Prototype模式的类图
相关的设计模式
Flyweight模式
使用Prototype模式可以生成一个与当前实例的状态完全相同的实例
而使用Flyweight模式可以在不同的地方使用同一个实例
Memento模式
使用Prototype模式可以生成一个与当前实例的状态完全相同的实例.
而使用Memento模式可以保存当前实例的状态,以实现快照和撤销功能
Composite模式以及Decorator模式
经常使用Composite模式和Decorator模式时,需要能够动态地创建复杂结构的实例.这时可以使用Prototype模式,以帮助我们方便地生成实例
Command模式
想要复制Command模式中出现的命令时,可以使用Prototype模式
第7章 Builder(建造者) 模式-组装复杂的实例
using System; using System.Runtime.InteropServices; using System.Text; namespace ConsoleApplication1 { public class Program { public static void Main(string[] args) { TextBuilder textBuilder = new TextBuilder(); Director director = new Director(textBuilder); director.construct(); string result = textBuilder.getResult(); Console.WriteLine(result); } } public abstract class ABuilder { public abstract void makeTitle(string title); public abstract void makeString(string str); public abstract void makeItems(string[] items); public abstract void close(); } public class TextBuilder : ABuilder { private StringBuilder buffer = new StringBuilder(); public override void makeTitle(string title) { buffer.Append("=========================\n"); buffer.Append("[" + title + "]\n"); buffer.Append("\n"); } public override void makeString(string str) { buffer.Append('^' + str + '\n'); buffer.Append("\n"); } public override void makeItems(string[] items) { for (int i = 0; i < items.Length; i++) { buffer.Append(" *" + items[i] + "\n"); } buffer.Append("\n"); } public override void close() { buffer.Append("=========================\n"); } public string getResult() { return buffer.ToString(); } } public class Director { private ABuilder builder; public Director(ABuilder builder) { this.builder = builder; } public void construct() { builder.makeTitle("Greeting"); builder.makeString("从早上到下午"); builder.makeItems(new string[] { "早上好", "下午好" }); builder.makeString("晚上"); builder.makeItems(new string[] { "晚上好", "晚安", "再见" }); builder.close(); } } }
Builder模式的类图
Builder模式的时序图
相关的设计模式
Template Method模式
在Builder模式中,Director角色控制Builder角色
在Template Method模式中,父类控制子类
Composite模式
有些情况下Builder模式生成的实例构成了Composite模式
Abstract Factory模式
Builder模式和Abstract Factory模式都用于生成复杂的模式
Facade 模式
在Builder模式中,Director角色通过组合Builder角色中的复杂方法向外部提供可以简单生成实例的接口(API)(相当于示例程序中的construct方法)
Facade模式中的Facade角色则是通过组合内部模块向外部提供可以简单调用的接口(API)
第8章 Abstract Factory(抽象工厂) 模式-将关联零件组装成产品
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Web; using System.Reflection; namespace ConsoleApplication1 { public class Program { public static void Main(string[] args) { AFactory factory = AFactory.getFactory(); ALink people = factory.createLink("人民日报", "http://www.people.com.cn/"); ALink gmw = factory.createLink("光明日报", "http://www.gmw.cn/"); ALink us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/"); ALink jp_yahoo = factory.createLink("Yahoo!Japn", "http://www.yahoo.co.jp/"); ALink excite = factory.createLink("Excite", "http://www.excite.com/"); ALink google = factory.createLink("Google", "http://www.google.com/"); ATray traynews = factory.createTray("日报"); traynews.add(people); traynews.add(gmw); ATray trayyahoo = factory.createTray("Yahoo!"); trayyahoo.add(us_yahoo); trayyahoo.add(jp_yahoo); ATray traysearch = factory.createTray("检索引擎"); traysearch.add(trayyahoo); traysearch.add(excite); traysearch.add(google); APage page = factory.createPage("LinkPage", "void"); page.add(traynews); page.add(traysearch); page.output(); } } public abstract class AItem { protected string caption; public AItem(string caption) { this.caption = caption; } public abstract string makeHTML(); } public abstract class ALink : AItem { protected string url; public ALink(string caption, string url) : base(caption) { this.url = url; } } public class ListLink : ALink { public ListLink(string caption, string url) : base(caption,url) { } public override string makeHTML() { return " <li><a href=\"" + url + "\">" + caption + "</a></li>\n"; } } public abstract class ATray : AItem { protected List<AItem> tray = new List<AItem>(); public ATray(string caption) : base(caption) { } public void add(AItem item) { tray.Add(item); } } public class ListTray : ATray { public ListTray(string caption) : base(caption) { } public override string makeHTML() { StringBuilder buffer = new StringBuilder(); buffer.Append("<li>\n"); buffer.Append(caption + "\n"); buffer.Append("<ul>\n"); foreach (var item in tray) { buffer.Append(item.makeHTML()); } buffer.Append("</ul>\n"); buffer.Append("</li>\n"); return buffer.ToString(); } } public abstract class APage { protected string title; protected string author; protected List<AItem> content = new List<AItem>(); public APage(string title, string author) { this.title = title; this.author = author; } public void add(AItem item) { content.Add(item); } public void output() { Console.WriteLine(makeHTML()); } public abstract string makeHTML(); } public class ListPage : APage { public ListPage(string title, string author) : base(title,author) { } public override string makeHTML() { StringBuilder buffer = new StringBuilder(); buffer.Append("<html><head></title>" + title + "</title></head>\n"); buffer.Append("<body>\n"); buffer.Append("<h1>" + title + "</h1>\n"); buffer.Append("<ul>\n"); foreach (var item in content) { buffer.Append(item.makeHTML()); } buffer.Append("</ul>\n"); buffer.Append("<hr><address>" + author + "</address>"); buffer.Append("</body></html>"); return buffer.ToString(); } } public abstract class AFactory { public static AFactory getFactory() { return new ListFactory(); } public abstract ALink createLink(string caption, string url); public abstract ATray createTray(string caption); public abstract APage createPage(string title, string author); } public class ListFactory : AFactory { public override ALink createLink(string caption, string url) { return new ListLink(caption,url); } public override ATray createTray(string caption) { return new ListTray(caption); } public override APage createPage(string title, string author) { return new ListPage(title,author); } } }
Abstract Factory模式
相关的设计模式
Builder模式
Abstract Factory模式通过调用抽象产品的接口(API)来组装抽象产品,生成具有复杂结构的实例.
Factory Method模式
有时Abstract Factory模式中零件和产品的生成会使用到Factory Method模式.
Composite模式
有时Abstract Factory模式在制作产品时会使用Composite模式
Singleton模式
有时Abstract Factory模式中的具体工厂会使用Singleton模式
第4部分 分开考虑
第9章 Brige(桥接) 模式-将类的功能层次结构与实现层次结构分离
类的功能层次结构
父类具有基本功能
在子类中增加新的功能
类的实现层次结构
父类通过声明抽象方法来定义接口(API)
子类通过实现具体方法来实现接口(API)
using System; using System.Collections.Generic; using System.Linq; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { Display d1 = new Display(new StringDisplayImpl("Hello,China.")); Display d2 = new CountDisplay(new StringDisplayImpl("Hello,World.")); CountDisplay d3 = new CountDisplay(new StringDisplayImpl("Hello,Universe")); d1.display(); d2.display(); d3.display(); d3.multiDisplay(5); } } public class Display { private ADisplayImpl impl; public Display(ADisplayImpl impl) { this.impl = impl; } public void open() { impl.rawOpen(); } public void print() { impl.rawPrint(); } public void close() { impl.rawClose(); } public void display() { open(); print(); close(); } } public class CountDisplay : Display { public CountDisplay(ADisplayImpl impl) : base(impl) { } public void multiDisplay(int times) { open(); for (int i = 0; i < times; i++) { print(); } close(); } } public abstract class ADisplayImpl { public abstract void rawOpen(); public abstract void rawPrint(); public abstract void rawClose(); } public class StringDisplayImpl : ADisplayImpl { private string str; private int width; public StringDisplayImpl(string str) { this.str = str; this.width = str.ToCharArray().Length; } public override void rawOpen() { printLine(); } public override void rawPrint() { Console.WriteLine("|" + str + "|"); } public override void rawClose() { printLine(); } private void printLine() { Console.Write("+"); for (int i = 0; i < width; i++) { Console.Write("-"); } Console.WriteLine("+"); } } }
Birdge 模式的类图
相关的设计模式
Template Method模式
在Template Method模式中使用了“类的实现层次结构".父类调用抽象方法,而子类实现抽象方法
Abstract Factory模式
为了能够根据需求设计出良好的ConcreteImplement角色,有时我们会使用Abstract Factory模式
Adapter模式
使用Bridge模式可以达到类的功能层次结构与类的实现层次结构分离的目的,并在此基础上使这些层次结构结合起来.
而使用Adapter模式则可以结合那些功能上相似但是接口(API)不同的类
第10章 Strategy(策略) 模式-整体地替换算法
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Runtime.CompilerServices; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { int seed1 = 314; int seed2 = 15; Player player1 = new Player("Taro",new WinningStrategy(seed1)); Player player2 = new Player("Hana",new ProbStrategy(seed2)); for (int i = 0; i < 10000; i++) { Hand nextHand1 = player1.nextHand(); Hand nextHand2 = player2.nextHand(); if (nextHand1.isStrongerThan(nextHand2)) { Console.WriteLine("Winner:" + player1); player1.win(); player2.lose(); } else if (nextHand2.isStrongerThan(nextHand1)) { Console.WriteLine("Winner:" + player2); player1.lose(); player2.win(); } else { Console.WriteLine("Even..."); player1.even(); player2.even(); } } Console.WriteLine("Total result:"); Console.WriteLine(player1.toString()); Console.WriteLine(player2.toString()); } } public class Hand { public static int HANDVALUE_GUU = 0; public static int HANDVALUE_CHO = 1; public static int HANDVALUE_PAA = 2; private int handvalue; public static Hand[] hand = { new Hand(HANDVALUE_GUU), new Hand(HANDVALUE_CHO), new Hand(HANDVALUE_PAA), }; public static string[] name = { "石头","剪刀","布" }; private Hand(int handvalue) { this.handvalue = handvalue; } public static Hand getHand(int handvalue) { return hand[handvalue]; } public bool isStrongerThan(Hand h) { return fight(h) == 1; } public bool isWeakerThan(Hand h) { return fight(h) == -1; } private int fight(Hand h) { if (this == h) { return 0; } else if ((this.handvalue + 1) % 3 == h.handvalue) { return 1; } else { return -1; } } public string toString() { return name[handvalue]; } } public interface IStrategy { Hand nextHand(); void study(bool win); } public class WinningStrategy : IStrategy { private Random random; private bool won = false; private Hand prevHand; public WinningStrategy(int seed) { random = new Random(seed); } public Hand nextHand() { if (!won) { prevHand = Hand.getHand(random.Next(3)); } return prevHand; } public void study(bool win) { won = win; } } public class ProbStrategy : IStrategy { private Random random; private int prevHandValue = 0; private int currentHandValue = 0; private int[,] history = { {1,1,1}, {1,1,1}, {1,1,1}, }; public ProbStrategy(int seed) { random = new Random(); } public Hand nextHand() { int bet = random.Next(getSum(currentHandValue)); int handvalue = 0; if (bet < history[currentHandValue, 0]) { handvalue = 0; } else if (bet < history[currentHandValue, 0] + history[currentHandValue, 1]) { handvalue = 1; } else { handvalue = 2; } prevHandValue = currentHandValue; currentHandValue = handvalue; return Hand.getHand(handvalue); } private int getSum(int hv) { int sum = 0; for (int i = 0; i < 3; i++) { sum += history[hv,i]; } return sum; } public void study(bool win) { if (win) { history[prevHandValue,currentHandValue]++; } else { history[prevHandValue, (currentHandValue + 1) % 3]++; history[prevHandValue, (currentHandValue + 2) % 3]++; } } } public class Player { private string name; private IStrategy strategy; private int wincount; private int losecount; private int gamecount; public Player(string name, IStrategy strategy) { this.name = name; this.strategy = strategy; } public Hand nextHand() { return strategy.nextHand(); } public void win() { strategy.study(true); wincount++; gamecount++; } public void lose() { strategy.study(false); losecount++; gamecount++; } public void even() { gamecount++; } public string toString() { return "[" + name + ":" + gamecount + " games, " + wincount + " win, " + losecount + " lose" + "]"; } } }
Strategy模式的类图
相关的设计模式
Flyweight模式
有时会使用Flyweight模式让多个地方可以共用ConcreteStrategy角色
AbstractFactory模式
使用Strategy模式可以整体地替换算法.
使用Abstract Factory模式则可以整体地替换具体工厂,零件和产品.
State模式
使用Strategy模式和State模式都可以替换被委托对象,而且它们之间的关系也很相似.但是两种模式的目的不同.
在Strategy模式中,ConcreteStrategy角色是表示算法的类.在Strategy模式中,可以替换被委托对象的类.当然如果没有必要,也可以不替换.
而在State模式中,ConcreteState角色是表示"状态"的类.在State模式中,每次状态变化时,被委托对象的类都必定会被替换.
第5部分 一致性
第11章 Composite(组合) 模式-容器与内容的一致性
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Runtime.CompilerServices; using System.Runtime.InteropServices.ComTypes; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { Console.WriteLine("Making root entries..."); Directory rootdir = new Directory("root"); Directory binddir = new Directory("bin"); Directory tmpdir = new Directory("tmp"); Directory usrdir = new Directory("usr"); rootdir.add(binddir); rootdir.add(tmpdir); rootdir.add(usrdir); binddir.add(new File("vi", 10000)); binddir.add(new File("latex", 20000)); rootdir.printList(); Console.WriteLine(""); Console.WriteLine("Making user entries..."); Directory yuki = new Directory("yuki"); Directory hanako = new Directory("hanako"); Directory tomura = new Directory("tomura"); usrdir.add(yuki); usrdir.add(hanako); usrdir.add(tomura); yuki.add(new File("diary.html", 100)); yuki.add(new File("Composite.java", 200)); hanako.add(new File("memo.tex", 300)); hanako.add(new File("game.doc", 400)); hanako.add(new File("junk.mail", 500)); rootdir.printList(); } } public abstract class AEntry { public abstract string getName(); public abstract int getSize(); public AEntry add(AEntry entry) { throw new NotImplementedException(); } public void printList() { printList(""); } public abstract void printList(string prefix); public override string ToString() { return getName() + " (" + getSize() + ") "; } } public class File : AEntry { private string name; private int size; public File(string name, int size) { this.name = name; this.size = size; } public override string getName() { return name; } public override int getSize() { return size; } public override void printList(string prefix) { Console.WriteLine(prefix + "/" + this); } } public class Directory : AEntry { private string name; private List<AEntry> entries = new List<AEntry>(); public Directory(string name) { this.name = name; } public override string getName() { return name; } public override int getSize() { int size = 0; foreach (var item in entries) { size += item.getSize(); } return size; } public AEntry add(AEntry entry) { entries.Add(entry); return this; } public override void printList(string prefix) { Console.WriteLine(prefix + "/" + this); foreach (var item in entries) { item.printList(prefix + "/" + name); } } } }
Composite模式的类图
相关的设计模式
Command模式
Visitor模式
可以使用Visitor模式访问Composite模式中的递归结构
第12章 Decorator(装饰) 模式-装饰边框与被装饰物的一致性
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { ADisplay b1 = new StringDisplay("Hello,World."); ADisplay b2 = new SideBorder(b1,'#'); ADisplay b3 = new FullBorder(b2); b1.show(); b2.show(); b3.show(); ADisplay b4 = new SideBorder( new FullBorder( new FullBorder( new SideBorder( new FullBorder( new StringDisplay("Hello") ), '*' ) ) ), '/' ); b4.show(); } } public abstract class ADisplay { public abstract int getColumns(); public abstract int getRows(); public abstract string getRowText(int row); public void show() { for (int i = 0; i < getRows(); i++) { Console.WriteLine(getRowText(i)); } } } public class StringDisplay : ADisplay { private string str; public StringDisplay(string str) { this.str = str; } public override int getColumns() { return str.ToCharArray().Length; } public override int getRows() { return 1; } public override string getRowText(int row) { if (row == 0) { return str; } else { return null; } } } public abstract class ABorder : ADisplay { protected ADisplay display; protected ABorder(ADisplay display) { this.display = display; } } public class SideBorder : ABorder { private char borderChar; public SideBorder(ADisplay display, char ch) : base(display) { this.borderChar = ch; } public override int getColumns() { return 1 + display.getColumns() + 1; } public override int getRows() { return display.getRows(); } public override string getRowText(int row) { return borderChar + display.getRowText(row) + borderChar; } } public class FullBorder : ABorder { public FullBorder(ADisplay display) : base(display) { } public override int getColumns() { return 1 + display.getColumns() + 1; } public override int getRows() { return 1 + display.getRows() + 1; } public override string getRowText(int row) { if (row == 0) { return "+" + makeLine('-', display.getColumns()) + "+"; } else if (row == display.getRows() + 1) { return "+" + makeLine('-', display.getColumns()) + "+"; } else { return "|" + display.getRowText(row - 1) + "|"; } } private string makeLine(char ch, int count) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < count; i++) { buf.Append(ch); } return buf.ToString(); } } }
Decorator模式的类图
相关的设计模式
Adapter模式
Decorator模式可以在不改变被装饰物的接口(API)的前提下,为被装饰物添加边框(透明性)
Adapter模式用于适配两个不同的接口(API)
Strategy模式
Decorator模式可以像改变被装饰物的边框或是被装饰物添加多重边框那样,来增加类的功能.
Stragety模式通过整体地替换算法来改变类的功能
第6部分 访问数据结构
第13章 Visitor(访问者) 模式-访问数据结构并处理数据
using System; using System.Collections; using System.Collections.Generic; namespace ConsoleApplication1 { public class Program { public static void Main(string[] args) { Console.WriteLine("Making root entries..."); Directory rootdir = new Directory("root"); Directory bindir = new Directory("bin"); Directory tmpdir = new Directory("tmp"); Directory usrdir = new Directory("usr"); rootdir.add(bindir); rootdir.add(tmpdir); rootdir.add(usrdir); bindir.add(new File("vi", 100000)); bindir.add(new File("latex", 20000)); rootdir.accept(new ListVisitor()); } } public abstract class AVisitor { public abstract void visit(File file); public abstract void visit(Directory dir); } public class ListVisitor : AVisitor { private string currentdir = ""; public override void visit(File file) { Console.WriteLine(currentdir + "/" + file); } public override void visit(Directory directory) { Console.WriteLine(currentdir + "/" + directory); string savedir = currentdir; currentdir = currentdir + "/" + directory.getName(); foreach (var item in directory.dir) { item.accept(this); } currentdir = savedir; } } public interface IElement { void accept(AVisitor v); } public abstract class AEntry : IElement { public abstract string getName(); public abstract int getSize(); public AEntry add(AEntry entry) { throw new NotImplementedException(); } public override string ToString() { return getName() + " (" + getSize() + ")"; } public abstract void accept(AVisitor v); } public class File : AEntry { private string name; private int size; public File(string name, int size) { this.name = name; this.size = size; } public override string getName() { return name; } public override int getSize() { return size; } public override void accept(AVisitor v) { v.visit(this); } } public class Directory : AEntry { private string name; public List<AEntry> dir = new List<AEntry>(); public Directory(string name) { this.name = name; } public override string getName() { return name; } public override int getSize() { int size = 0; foreach (var item in dir) { size += item.getSize(); } return size; } public AEntry add(AEntry entry) { dir.Add(entry); return this; } public override void accept(AVisitor v) { v.visit(this); } } }
Visitor模式的类图
相关的设计模式
Iterator模式
Iterator模式和Visitor模式都是在某种数据结构上进行处理
Iterator模式用于逐个遍历保存在数据结构中的元素
Visitor模式用于对保存在数据结构中的元素进行某种特定的处理
Composite模式
有时访问者所访问的数据结构会使用Composite模式
Interpreter模式
在Interpreter模式中,有时会使用Visitor模式
第14章 Chain of Responsibility(职责链) 模式-推卸责任
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading; namespace Test1 { class Program { static void Main(string[] args) { ASupport alice = new NotSupport("Alice"); ASupport bob = new LimitSupport("Bob",100); ASupport charlie = new SpecialSupport("Charlie",429); ASupport diana = new LimitSupport("Diana",200); ASupport elmo = new OddSupport("Elmo"); ASupport fred = new LimitSupport("Fred",300); alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred); for (int i = 0; i < 500; i += 33) { alice.support(new Trouble(i)); } } } public class Trouble { private int number; public Trouble(int number) { this.number = number; } public int getNumber() { return number; } public string toString() { return "[Trouble " + number + "]"; } } public abstract class ASupport { private string name; private ASupport next; public ASupport(string name) { this.name = name; } public ASupport setNext(ASupport next) { this.next = next; return next; } public void support(Trouble trouble) { if (resolve(trouble)) { done(trouble); } else if(next != null) { next.support(trouble); } else { fail(trouble); } } public override string ToString() { return "[" + name + "]"; } protected abstract bool resolve(Trouble trouble); protected void done(Trouble trouble) { Console.WriteLine(trouble + " is resolved by " + this + "."); } protected void fail(Trouble trouble) { Console.WriteLine(trouble + " cannot be resolved."); } } public class NotSupport : ASupport { public NotSupport(string name) : base(name) { } protected override bool resolve(Trouble trouble) { return false; } } public class LimitSupport : ASupport { private int limit; public LimitSupport(string name, int limit) : base(name) { this.limit = limit; } protected override bool resolve(Trouble trouble) { if (trouble.getNumber() < limit) { return true; } else { return false; } } } public class OddSupport : ASupport { public OddSupport(string name) : base(name) { } protected override bool resolve(Trouble trouble) { if (trouble.getNumber() % 2 == 1) { return true; } else { return false; } } } public class SpecialSupport : ASupport { private int number; public SpecialSupport(string name, int number) : base(name) { this.number = number; } protected override bool resolve(Trouble trouble) { if (trouble.getNumber() == number) { return true; } else { return false; } } } }
Chain of Responsibility模式的类图
相关的设计模式
Composite模式
Handler角色经常会使用Composite模式
Command模式
有时会使用Command模式向Handler角色发送请求
第7部分 简单化
第15章 Facade(外观) 模式-简单窗口
using System; namespace Test1 { class Program { static void Main(string[] args) { Facade f = new Facade(); f.Interface(); } } public class Facade { private ClassA a; private ClassB b; private ClassC c; public Facade() { a = new ClassA(); b = new ClassB(); c = new ClassC(); } public void Interface() { a.method(); b.method(); c.method(); } } public class ClassA { public void method() { Console.WriteLine("ClassA Method"); } } public class ClassB { public void method() { Console.WriteLine("ClassB Method"); } } public class ClassC { public void method() { Console.WriteLine("ClassC Method"); } } }
Facade模式的类图
相关的设计模式
Abstract Factory模式
可以将Abstract Factory模式看作生成复杂实例时的Facade模式.因为它提供了"要想生成这个实例只需要调用这个方法就OK了"的简单接口
Singleton 模式
有时会使用SIngleton模式创建Facade角色
Mediator 模式
在Facade模式中,Facade角色单方面地使用其他角色来提供高层接口(API)
而在Mediator模式中,Mediator角色作为Colleague角色间的仲裁者负责调停.可以说,Facade模式是单向的,而Mediator角色是双向的.
第16章 Mediator(中介者) 模式-只有一个仲裁者
using System; namespace Test1 { class Program { static void Main(string[] args) { IMediator mediator = new LoginFrame(); mediator.colleagueChanged(); } } public interface IMediator { void createColleagues(); void colleagueChanged(); } public interface IColleague { void setMediator(IMediator mediator); void setColleagueEnabled(bool enabled); } public class ColleagueButton : IColleague { private IMediator mediator; private string caption; public ColleagueButton(string caption) { this.caption = caption; } public void setMediator(IMediator mediator) { this.mediator = mediator; } public void setColleagueEnabled(bool enabled) { Console.WriteLine("enabled:" + enabled); } } public class ColleagueTextField : IColleague { private IMediator mediator; private string caption; public ColleagueTextField(string caption) { this.caption = caption; } public void setMediator(IMediator mediator) { this.mediator = mediator; } public void setColleagueEnabled(bool enabled) { Console.WriteLine("enabled:" + enabled); } public void textValueChanged() { mediator.colleagueChanged(); } } public class ColleagueCheckbox : IColleague { private IMediator mediator; private string caption; public ColleagueCheckbox(string caption) { this.caption = caption; } public void setMediator(IMediator mediator) { this.mediator = mediator; } public void setColleagueEnabled(bool enabled) { Console.WriteLine("enabled:" + enabled); } public void itemStateChanged() { mediator.colleagueChanged(); } } public class LoginFrame : IMediator { private ColleagueButton button; private ColleagueCheckbox checkbox; private ColleagueTextField textField; public LoginFrame() { createColleagues(); button.setMediator(this); checkbox.setMediator(this); textField.setMediator(this); } public void createColleagues() { button = new ColleagueButton("Button"); checkbox = new ColleagueCheckbox("Checkbox"); textField = new ColleagueTextField("TexField"); } public void colleagueChanged() { button.setColleagueEnabled(false); checkbox.setColleagueEnabled(false); textField.setColleagueEnabled(false); } } }
Mediator 模式中的类图
相关的设计模式
Facade模式
在Mediator模式中,Mediator角色与Colleague角色进行交互.
而在Facade模式中,Facade角色单方面地使用其他角色来对外提供高层接口(API).因此,可以说Mediator模式是双向的,而Facade模式是单向的.
Observer模式
有时会使用Observer模式来实现Mediator角色与Colleague角色之间的通信
第8部分 管理状态
第17章 Observer(观察者) 模式-发送状态变化通知
using System; using System.Collections.Generic; using System.Net; namespace Test1 { class Program { static void Main(string[] args) { NumberGenerator generator = new RandomNumberGenerator(); Observer observer1 = new DigitObserver(); Observer observer2 = new GraphObserver(); generator.addObserver(observer1); generator.addObserver(observer2); generator.execute(); } } public interface Observer { void update(NumberGenerator generator); } public class DigitObserver : Observer { public void update(NumberGenerator generator) { Console.WriteLine("DigitObserver:" + generator.getNumber()); System.Threading.Thread.Sleep(100); } } public class GraphObserver : Observer { public void update(NumberGenerator generator) { Console.WriteLine("GraphObserver:"); int count = generator.getNumber(); for (int i = 0; i < count; i++) { Console.Write("*"); } Console.WriteLine(""); System.Threading.Thread.Sleep(100); } } public abstract class NumberGenerator { private List<Observer> observers = new List<Observer>(); public void addObserver(Observer observer) { observers.Add(observer); } public void deleteObserver(Observer observer) { observers.Remove(observer); } public void notifyObservers() { foreach (var item in observers) { item.update(this); } } public abstract int getNumber(); public abstract void execute(); } public class RandomNumberGenerator : NumberGenerator { private Random random = new Random(); private int number; public override int getNumber() { return number; } public override void execute() { for (int i = 0; i < 20; i++) { number = random.Next(50); notifyObservers(); } } } }
Observer模式的类图
相关的设计模式
Mediator模式
在Mediator模式中,有时会使用Observer模式来实现Mediator角色与Colleague角色之间的通信
就"发送状态变化通知"这一点而言,Mediator模式与Observer模式是类似的.不过,两种模式中,通知的目的和视角不同.
在Mediator模式中,虽然也会发送通知,不过那不过是为了对Colleague角色进行仲裁而已.
而在Observer模式中,将Subject角色的状态变化通知给Observer角色的目的则主要是为了使Subject角色和Observer角色同步.
第18章 Memento(备忘录) 模式-保存对象状态
using System; using System.CodeDom; using System.Collections; using System.Collections.Generic; using System.ComponentModel.Design; namespace ConsoleApplication1 { public class Program { public static void Main(string[] args) { Gamer gamer = new Gamer(100); Memento memento = gamer.createMemento(); for (int i = 0; i < 100; i++) { Console.WriteLine("===== " + i); Console.WriteLine("当前状态:" + gamer); gamer.bet(); Console.WriteLine("所持金钱为:" + gamer.getMoney() + "元."); if (gamer.getMoney() > memento.getMoney()) { Console.WriteLine(" (所持金钱增加了许多,因此保存游戏当前的状态)"); memento = gamer.createMemento(); } else if (gamer.getMoney() < memento.getMoney() / 2) { Console.WriteLine(" (所持金钱减少了许多,因此将游戏恢复至以前的状态)"); gamer.restoreMemento(memento); } } } } public class Memento { private int money; private ArrayList fruits; public Memento(int money) { this.money = money; this.fruits = new ArrayList(); } public int getMoney() { return money; } public void addFruit(string fruit) { fruits.Add(fruit); } public ArrayList getFruits() { return (ArrayList)fruits.Clone(); } } public class Gamer { private int money; private ArrayList fruits = new ArrayList(); private Random random = new Random(); private static string[] fruitsname = { "苹果","葡萄","香蕉","橘子" }; public Gamer(int money) { this.money = money; } public int getMoney() { return money; } public void bet() { int dice = random.Next(6) + 1; if (dice == 1) { money += 100; Console.WriteLine("所持金钱增加了."); } else if (dice == 2) { money /= 2; Console.WriteLine("所持金钱减半了."); } else if (dice == 6) { string f = getFruit(); Console.WriteLine("获得了水果(" + f + ")."); fruits.Add(f); } else { Console.WriteLine("什么都没有发生"); } } public Memento createMemento() { Memento m = new Memento(money); foreach (var item in fruits) { if (item.ToString().StartsWith("好吃的")) { m.addFruit(item.ToString()); } } return m; } public void restoreMemento(Memento memento) { this.money = memento.getMoney(); this.fruits = memento.getFruits(); } public override string ToString() { var str = "["; foreach (var item in fruits) { str += item.ToString() + ","; } str += "]"; return "[money = " + money + ", fruits = " + str; } private string getFruit() { string prefix = ""; if (random.Next(2) == 1) { prefix = "好吃的"; } return prefix + fruitsname[random.Next(fruitsname.Length)]; } } }
Memento模式的类图
相关的设计模式
Command模式
在使用Command模式处理命令时,可以使用Memento模式实现撤销功能
Prototype模式
在Memento模式中,为了能够实现快照和撤销功能,保存了对象当前的状态.保存的信息只是在恢复状态时所需要的那部分信息.
而在Prototype模式中,会生成一个与当前实例完全相同的另外一个实例.这两个实例的内容完全一样.
State模式
在Memento模式中,是用"实例"表示状态
而在State模式中,则是用"类"表示状态
第19章 State(状态) 模式-用类表示状态
State模式的类图
相关的设计模式
Singleton模式
Singleton模式常常会出现在ConcreteState角色中.
Flyweight模式
在表示状态的类中并没有定义任何实例字段.因此,有时我们可以使用Flyweight模式在多个Context角色之间共享ConcreteState角色
第9部分 避免浪费
第20章 Flyweight(享元) 模式-共享对象,避免浪费
using System; using System.Collections.Generic; using System.Net; namespace Test2 { class Program { static void Main(string[] args) { BigString bs = new BigString("aascd"); bs.print(); } } public class BigChar { private char charname; private string fontdata; public BigChar(char charname) { this.charname = charname; fontdata = "#" + charname +"#"; } public void print() { Console.WriteLine(fontdata); } } public class BigCharFactory { private Dictionary<char,BigChar> pool = new Dictionary<char, BigChar>(); private static BigCharFactory singleton = new BigCharFactory(); private BigCharFactory() { } public static BigCharFactory getInstance() { return singleton; } public BigChar getBigChar(char charname) { BigChar bc; if (!pool.TryGetValue(charname, out bc)) { bc = new BigChar(charname); } return bc; } } public class BigString { private BigChar[] bigchars; public BigString(string str) { bigchars = new BigChar[str.Length]; BigCharFactory factory = BigCharFactory.getInstance(); for (int i = 0; i < bigchars.Length; i++) { bigchars[i] = factory.getBigChar(str.ToCharArray()[i]); } } public void print() { for (int i = 0; i < bigchars.Length; i++) { bigchars[i].print(); } } } }
Flyweight模式的类图
相关的设计模式
Proxy模式
如果生成实例的处理需要花费较长时间,那么使用Flyweight模式可以提高程序的处理速度.
而Proxy模式则是通过设置代理提高程序的处理速度
Composite模式
有时可以使用Flyweight模式共享Composite模式中的Leaf角色
Singleton模式
在FlyweightFactory角色中有时会使用Singleton模式.
第21章 Proxy(代理) 模式-只在必要时生成实例
using System; using System.Collections.Generic; using System.Net; namespace Test2 { class Program { static void Main(string[] args) { Printable p = new PrinterProxy("Alice"); Console.WriteLine("现在的名字是" + p.getPrinterName() + "."); p.setPrinterName("Bob"); Console.WriteLine("现在的名字是" + p.getPrinterName() + "."); p.print("Hello,world"); } } public interface Printable { void setPrinterName(string name); string getPrinterName(); void print(string str); } public class Printer : Printable { private string name; public Printer() { heavyJob("正在生成Printer实例"); } public Printer(string name) { this.name = name; heavyJob("正在生成Printer的实例(" + name +")"); } public void setPrinterName(string name) { this.name = name; } public string getPrinterName() { return name; } public void print(string str) { Console.WriteLine("=== " + name + " ==="); Console.WriteLine(str); } private void heavyJob(string msg) { Console.WriteLine(msg); for (int i = 0; i < 5; i++) { System.Threading.Thread.Sleep(1000); Console.Write("."); } Console.WriteLine("结束."); } } public class PrinterProxy : Printable { private string name; private Printer real; public PrinterProxy() { } public PrinterProxy(string name) { this.name = name; } public void setPrinterName(string name) { if (real != null) { real.setPrinterName(name); } this.name = name; } public string getPrinterName() { return name; } public void print(string str) { realize(); real.print(str); } private void realize() { if (real == null) { real = new Printer(name); } } } }
Proxy模式的类图
相关的设计模式
Adapter模式
Adapter模式适配了两种具有不同接口(API)的对象,以使它们可以一同工作.
而在Proxy模式中,Proxy角色与RealSubject角色的接口(API)是相同的(透明性)
Decorator模式
Decorator模式与Proxy模式在实现上很相似,不过它们的使用目的不同.
Decorator模式的目的在于增加新的功能.而在Proxy模式中,与增加新功能相比,它更注重通过设置代理人的方式来减轻本人的工作负担
第10部分 用类来表现
第22章 Command(命令) 模式-命令也是类
using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Net; using System.Threading; namespace Test2 { class Program { static void Main(string[] args) { MacroCommand history = new MacroCommand(); Drawable draw = new DrawCanvas(400,400,history); Command cmd = new DrawCommand(draw, new Point(50, 50)); history.append(cmd); cmd.execute(); } } public interface Command { void execute(); } public class MacroCommand : Command { private Stack<Command> commands = new Stack<Command>(); public void execute() { commands.Pop().execute(); foreach (var item in commands) { item.execute(); } } public void append(Command command) { if (command != this) { commands.Push(command); } } public void undo() { if (commands.Count != 0) { commands.Pop(); } } public void clear() { commands.Clear(); } } public class DrawCommand : Command { protected Drawable drawable; private Point position; public DrawCommand(Drawable drawable, Point position) { this.drawable = drawable; this.position = position; } public void execute() { drawable.draw(position.X,position.Y); } } public interface Drawable { void draw(int x, int y); } public class DrawCanvas : Drawable { private int radius = 6; private MacroCommand history; public DrawCanvas(int width, int height, MacroCommand history) { this.history = history; } public void paint() { history.execute();; } public void draw(int x, int y) { Console.WriteLine("Draw X:" + x + ", Y:" + y); } } }
Command模式的类图
相关的设计模式
Composite模式
有时会使用Composite模式实现宏命令(macrocommand)
Memento模式
有时会使用Memento模式来保存Command角色的历史记录
Prototype模式
有时会使用Prototype模式复制发生的事件(生成的命令)
第23章 Interpreter(解释器) 模式-语法规则也是类
Interpreter模式的类图
相关的设计模式
Composite模式
NonterminalExpression角色多是递归结构,因此常会使用Composite模式来实现NonterminalExpression角色.
Flyweight模式
有时会使用Flyweight模式来共享TerminalExperssion角色
Visitor模式
在推导出语法树后,有时会使用Visitor模式来访问语法树的各个节点