图解设计模式 (结城浩 著)

第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部分 简单化

  第15章 Facade(外观) 模式-简单窗口 (已看)

  第16章 Mediator(中介者) 模式-只有一个仲裁者 (已看)

第8部分 管理状态

  第17章 Observer(观察者) 模式-发送状态变化通知 (已看)

  第18章 Memento(备忘录) 模式-保存对象状态 (已看)

  第19章 State(状态) 模式-用类表示状态 (已看)

第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;
        }
    }
}
View Code

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();
        }
    }
    
}
View Code

类适配器模式的类图(使用继承)

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 + "*");
        }
    }
}
View Code

类适配器模式的类图(使用继承)

相关的设计模式

  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("+");
        }
    }
}
View Code

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;
        }
    }
}
View Code

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;
        }
    }
}
View Code

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();
        }
        
        
    }

}
View Code

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();
        }
    }

}
View Code

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);
        }
    }
    
}
View Code

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("+");
        }
    }
}
View Code

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" + "]";
        }
    }
}
View Code

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);
            }
        }
    }
}
View Code

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();
        }
    }
}
View Code

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);
        }
    }
}
View Code

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;
            }
        }
    }
}
View Code

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");
        }
    }
}
View Code

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);
        }

    }
}
View Code

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();
            }
        }
    }
}
View Code

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)];
        }
    }

}
View Code

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();
            }
        }
    }
}
View Code

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);
            }
        }
    }
}
View Code

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);
        }
    }
}
View Code

Command模式的类图

相关的设计模式

  Composite模式

    有时会使用Composite模式实现宏命令(macrocommand)

  Memento模式

    有时会使用Memento模式来保存Command角色的历史记录

  Prototype模式

    有时会使用Prototype模式复制发生的事件(生成的命令)

  第23章 Interpreter(解释器) 模式-语法规则也是类

Interpreter模式的类图

相关的设计模式

  Composite模式

    NonterminalExpression角色多是递归结构,因此常会使用Composite模式来实现NonterminalExpression角色.

  Flyweight模式

    有时会使用Flyweight模式来共享TerminalExperssion角色

  Visitor模式

    在推导出语法树后,有时会使用Visitor模式来访问语法树的各个节点

转载于:https://www.cnblogs.com/revoid/p/6719867.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值