Commit 44c5c030 by O'Reilly Media, Inc.

Initial commit

parents
## Example files for the title:
# C# 3.0 Design Patterns, by Judith Bishop
[![C# 3.0 Design Patterns, by Judith Bishop](http://akamaicovers.oreilly.com/images/9780596527730/cat.gif)](https://www.safaribooksonline.com/library/view/title/9780596527730//)
The following applies to example files from material published by O’Reilly Media, Inc. Content from other publishers may include different rules of usage. Please refer to any additional usage rights explained in the actual example files or refer to the publisher’s website.
O'Reilly books are here to help you get your job done. In general, you may use the code in O'Reilly books in your programs and documentation. You do not need to contact us for permission unless you're reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from our books does not require permission. Answering a question by citing our books and quoting example code does not require permission. On the other hand, selling or distributing a CD-ROM of examples from O'Reilly books does require permission. Incorporating a significant amount of example code from our books into your product's documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN.
If you think your use of code examples falls outside fair use or the permission given here, feel free to contact us at <permissions@oreilly.com>.
Please note that the examples are not production code and have not been carefully testing. They are provided "as-is" and come with no warranty of any kind.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
// Adapter Pattern Example Judith Bishop Aug 2007
// Sets up a Coolbook
// This is D-J's as changed for the book
class AdapterPattern {
//class SpaceBookSystem {
public delegate void InputEventHandler(object sender, EventArgs e, string s);
//Adapter
public class MyCoolBook : MyOpenBook {
static SortedList<string, MyCoolBook> community =
new SortedList<string, MyCoolBook>(100);
Interact visuals;
public MyCoolBook(string name) : base(name) {
// create interact on the relavent thread, and start it!
new Thread(delegate() {
visuals = new Interact("CoolBook Beta");
visuals.InputEvent += new InputEventHandler(OnInput);
visuals.FormClosed += new FormClosedEventHandler(OnFormClosed);
Application.Run(visuals);
}).Start();
community[name] = this;
while (visuals == null) {
Application.DoEvents();
Thread.Sleep(100);
}
Add("Welcome to CoolBook " + Name);
}
private void OnFormClosed(object sender, FormClosedEventArgs e) {
community.Remove(Name);
}
private void OnInput(object sender, EventArgs e, string s) {
Add("\r\n");
Add(s, "Poked you");
}
public new void Poke(string who) {
Add("\r\n");
if (community.ContainsKey(who))
community[who].Add(Name, "Poked you");
else
Add("Friend " + who + " is not part of the community");
}
public new void Add(string message) {
visuals.Output(message);
}
public new void Add(string friend, string message) {
if (community.ContainsKey(friend))
community[friend].Add(Name + " : " + message);
else
Add("Friend " + friend + " is not part of the community");
}
}
//New Implementation (Adaptee)
public class Interact : Form {
public TextBox Wall { get; set; }
public Button Poke { get; set; }
public Interact() { }
public Interact(string title) {
Control.CheckForIllegalCrossThreadCalls = true;
Poke = new Button();
Poke.Text = "Poke";
this.Controls.Add(Poke);
Poke.Click += new EventHandler(Input);
Wall = new TextBox();
Wall.Multiline = true;
Wall.Location = new Point(0, 30);
Wall.Width = 300;
Wall.Height = 200;
Wall.Font = new Font(Wall.Font.Name, 12);
Wall.AcceptsReturn = true;
this.Text = title;
this.Controls.Add(Wall);
}
public event InputEventHandler InputEvent;
public void Input(object source, EventArgs e) {
string who = Wall.SelectedText;
if (InputEvent != null)
InputEvent(this, EventArgs.Empty, who);
}
public void Output(string message) {
if (this.InvokeRequired)
this.Invoke((MethodInvoker)delegate() { Output(message); });
else {
Wall.AppendText(message + "\r\n");
this.Show();
}
}
protected override void OnFormClosed(FormClosedEventArgs e) {
// Remove the interact and coolbook from the community here!
base.OnFormClosed(e);
}
}
// The RealSubject (ProxyPattern)
// CANNOT CHANGE
public class SpaceBook {
static SortedList<string, SpaceBook> community =
new SortedList<string, SpaceBook>(100);
string pages;
string name;
string gap = "\n\t\t\t\t";
static public bool Unique(string name) {
return community.ContainsKey(name);
}
internal SpaceBook(string n) {
name = n;
community[n] = this;
}
internal string Add(string s) {
pages += gap + s;
return gap + "======== " + name + "'s SpaceBook =========\n" +
pages +
gap + "\n===================================";
}
internal string Add(string friend, string message) {
return community[friend].Add(message);
}
internal void Poke(string who, string friend) {
community[who].pages += gap + friend + " poked you";
}
}
// Target (Adapter Pattern)
//CANNOT CHANGE
public class MyOpenBook {
SpaceBook myOpenBook;
public string Name { get; set; }
public static int Users { get; set; }
public MyOpenBook(string n) {
Name = n;
Users++;
myOpenBook = new SpaceBook(Name + "-" + Users);
}
public void Add(string message) {
Console.WriteLine(myOpenBook.Add(message));
}
public void Add(string friend, string message) {
Console.WriteLine(myOpenBook.Add(friend, Name + " : " + message));
}
public void Poke(string who) {
myOpenBook.Poke(who, Name);
}
public void SuperPoke(string who, string what) {
myOpenBook.Add(who, what + " you");
}
}
// The Client
static void Main() {
MyCoolBook judith = new MyCoolBook("Judith");
judith.Add("Hello world");
MyCoolBook tom = new MyCoolBook("Tom");
tom.Poke("Judith");
tom.Add("Hey, We are on CoolBook");
judith.Poke("Tom");
Console.ReadLine();
}
}
\ No newline at end of file
<Form Text="Currency calculator" Width="250" Height="180">
<Label Top="10" Text="Paid on hols" />
<TextBox Top="10" Left="100" Name="eurobox" />
<Label Top="40" Text="Charged" />
<TextBox Top="40" Left="100" Name="GBPbox" />
<Label Top="70" Text="Exchange rate is" />
<TextBox Top="70" Left="100" Name="ratebox" />
<Button Top="100" Name="equals" Text="=" />
<Button Top="100" Left="100" Name="clear" Text="Reset" />
</Form>
using System;
// Interpreter Pattern - Example Judith Bishop October 2007
// Sets up an object structure and interprets it with given data
static class ElementExtensions {
public static string gap;
public static void Print(this Element element) {
Console.WriteLine(gap+element + " " + element.Weight);
if (element.Part!=null) {
gap+=" ";
Print(element.Part.Next);
gap = gap.Substring(2);
}
if (element.Next!=null) Print(element.Next);
}
public static int Lab {get; set;}
public static int Test {get; set;}
public static void Summarize(this Element element) {
if (element is Lab) Lab += element.Weight;
else if (element is Test)
Test += element.Weight;
else if ((element is Midterm || element is Exam) && element.Part==null)
Test += element.Weight;
if (element.Part!=null) Summarize(element.Part.Next);
if (element.Next!=null) Summarize(element.Next);
}
public static int [] values;
public static int n;
public static Context context;
public static void SetUp (this Element element, Context c, int[] v) {
context = c;
context.Output=0;
values = v;
n = 0;
}
public static void Interpreter(this Element element) {
if (element is Lab || element is Test) {
context.Output += values[n]*element.Weight;
n++;
}
else
if ((element is Midterm || element is Exam) && element.Part==null) {
context.Output += values[n]*element.Weight;
n++;
}
if (element.Part!=null) Interpreter(element.Part.Next);
if (element.Next!=null) Interpreter(element.Next);
}
}
public class Element {
public int Weight {get; set;}
public Element Next {get; set;}
public Element Part {get; set;}
public virtual string Display() {
return Weight+"%";
}
int GetNumber (Context context) {
int atSpace = context.Input.IndexOf(' ');
int number = Int32.Parse(context.Input.Substring(1,atSpace));
context.Input = context.Input.Substring(atSpace+1);
return number;
}
public void Parse (Context context) {
string starters = "LTME";
if (context.Input.Length>0 && starters.IndexOf(context.Input[0])>=0) {
switch(context.Input[0]) {
case 'L':
Next=new Lab();
break;
case 'T':
Next=new Test();
break;
case 'M':
Next=new Midterm();
break;
case 'E':
Next = new Exam();
break;
}
Next.Weight = GetNumber(context);
if (context.Input.Length>0 && context.Input[0]=='(') {
context.Input = context.Input.Substring(1);
Next.Part = new Element();
Next.Part.Parse(context);
Element e = Next.Part;
while (e!=null) {
e.Weight = e.Weight * Next.Weight / 100;
e = e.Next;
}
context.Input = context.Input.Substring(2);
}
Next.Parse(context);
}
}
}
class Course : Element {
public string Name {get; set;}
public Course (Context context) {
Name = context.Input.Substring(0,6);
context.Input = context.Input.Substring(7);
}
public override string Display() {
return Name;
}
}
class Lab : Element {
}
class Test : Element {
}
class Midterm : Element {
}
class Exam : Element {
}
public class Context {
public string Input {get; set;}
public double Output {get; set;}
public Context(string c) {
Input = c;
Output = 0;
}
}
static class IntArrayExtension {
public static string Display (this int[] a) {
string s = "[";
foreach (int i in a)
s+=i+", ";
return s.Substring(0,s.Length-2)+"]";
}
}
class InterpreterPattern {
static void Main() {
string rules = "COS333 L2 L2 L2 L2 L2 M25 (L40 T60 ) L10 E55 (L28 T73 ) ";
int [][] values = new [] { new [] {80,0,100,100,85,51,52,50,57,56},
new [] {87,95,100,100,77,70,99,100,75,94},
new [] {0,55,100,65,55,75,73,74,71,72}};
Context context;
Console.WriteLine (rules+"\n");
context = new Context (rules);
Element course = new Course(context);
course.Parse(context);
Console.WriteLine("Visitor 1 - Course structure\n");
course.Print();
course.Summarize();
Console.WriteLine ("\n\nVisitor 2 - Summing the weights\nLabs "
+ElementExtensions.Lab + "% and Tests "
+ElementExtensions.Test + "%");
Console.WriteLine("\n\nVisitor 3 (Interpreter) ");
foreach (int [] student in values) {
Console.Write(student.Display());
course.SetUp(context, student);
course.Interpreter();
Console.WriteLine(" = "+context.Output/100);
}
}
}
/* Output
COS333 L2 L2 L2 L2 L2 M25 (L40 T60 ) L10 E55 (L28 T73 )
Visitor 1 - Course structure
Course 0
Lab 2
Lab 2
Lab 2
Lab 2
Lab 2
Midterm 25
Lab 10
Test 15
Lab 10
Exam 55
Lab 15
Test 40
Visitor 2 - Summing the weights
Labs 45% and Tests 55%
Visitor 3 (Interpreter)
[80, 0, 100, 100, 85, 51, 52, 50, 57, 56] = 56.15
[87, 95, 100, 100, 77, 70, 99, 100, 75, 94] = 89.88
[0, 55, 100, 65, 55, 75, 73, 74, 71, 72] = 70.8
*/
\ No newline at end of file
using System;
using System.Xml;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
public class Mirror {
// Mirrors by Hans Lombard June 2006, revised Sept 2007
// based on Views and Views-2 by Nigel Horspool, Judith Bishop and D-J Miller
// A general purpose interpreter for any .NET API
// Reads XML and executes the methods it represents
// This example assumes the Windows Form API only in the final line where
// Application.Run is called.
Stack objectStack;
List<Command> commands;
public object CurrentObject { get { return objectStack.Peek(); } }
public XmlTextReader Reader { get; set; }
public object LastObject { get; set; }
public Mirror(string spec) {
objectStack = new Stack();
objectStack.Push(null);
//Register the commands
commands = new List<Command>();
commands.Add(new ElementCommand());
commands.Add(new EndElementCommand());
commands.Add(new AttributeCommand());
Reader = new XmlTextReader(spec);
while (Reader.Read()) {
InterpretCommands();
bool b = Reader.IsEmptyElement;
if (Reader.HasAttributes) {
for (int i = 0; i < Reader.AttributeCount; i++) {
Reader.MoveToAttribute(i);
InterpretCommands();
}
}
if (b) Pop();
}
}
public void InterpretCommands() {
//Run through the commands and interpret
foreach (Command c in commands)
c.Interpret(this);
}
public void Push(object o) {
objectStack.Push(o);
}
public void Pop() {
LastObject = objectStack.Pop();
}
public object Peek() {
return objectStack.Peek();
}
}
public abstract class Command {
public abstract void Interpret (Mirror context);
}
//Handles an XML element. Creates a new object which reflects the XML
//element name
public class ElementCommand : Command {
public override void Interpret (Mirror context) {
if (context.Reader.NodeType != XmlNodeType.Element) return;
Type type = GetTypeOf(context.Reader.Name);
if (type == null) return;
object o = Activator.CreateInstance(type);
if (context.Peek() != null)
((Control)context.Peek()).Controls.Add((Control)o);
context.Push(o);
}
public Type GetTypeOf(string s) {
string ns = "System.Windows.Forms";
Assembly asm = Assembly.Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Type type = asm.GetType(ns + "." + s);
return type;
}
}
//Handles an XML end element. Removes the element from the object stack.
public class EndElementCommand : Command {
public override void Interpret (Mirror context) {
if (context.Reader.NodeType != XmlNodeType.EndElement) return;
context.Pop();
}
}
//Applies attributes to the current object. The attributes reflects to the properties
//of the object
public class AttributeCommand : Command {
public override void Interpret (Mirror context) {
if (context.Reader.NodeType != XmlNodeType.Attribute) return;
SetProperty(context.Peek(), context.Reader.Name, context.Reader.Value);
}
public void SetProperty(object o, string name, string val) {
Type type = o.GetType();
PropertyInfo property = type.GetProperty(name);
//Find an appropriate property to match the attribute name
if (property.PropertyType.IsAssignableFrom(typeof(string))) {
property.SetValue(o, val, null);
} else if (property.PropertyType.IsSubclassOf(typeof(Enum))) {
object ev = Enum.Parse(property.PropertyType, val, true);
property.SetValue(o, ev, null);
} else {
MethodInfo m = property.PropertyType.GetMethod("Parse", new Type[] { typeof(string) });
object newval = m.Invoke(null /*static */, new object[] { val });
property.SetValue(o, newval, null);
}
}
}
public class MainClass {
public static void Main() {
Mirror m = new Mirror("calc_winforms.xml");
Application.Run((Form)m.LastObject);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
// Iterator Pattern Example Judith Bishop September 2007
// Illustrates the use of LINQ with iterators on a tree structure
class Person {
public Person() {}
public string Name {get; set;}
public int Birth {get; set;}
public Person (string name, int birth) {
Name = name;
Birth = birth;
}
public override string ToString () {
return ("["+Name+", "+Birth+"]");
}
}
class Node <T> {
public Node () {}
public Node <T> Left{get; set;}
public Node <T> Right {get; set;}
public T Data {get; set;}
public Node (T d, Node <T> left, Node <T> right) {
Data = d;
Left = left;
Right = right;
}
}
// T is the data type. The Node type is built-in
class Tree <T> {
Node <T> root;
public Tree() {}
public Tree (Node <T> head) {
root = head;
}
public IEnumerable <T> Preorder {
get {return ScanPreorder (root);}
}
// Enumerator with Filter
public IEnumerable <T> Where (Func <T, bool> filter){
foreach (T p in ScanPreorder(root))
if (filter(p)==true)
yield return p;
}
// Enumerator with T as Person
private IEnumerable <T> ScanPreorder (Node <T> root) {
yield return root.Data;
if (root.Left !=null)
foreach (T p in ScanPreorder (root.Left))
yield return p;
if (root.Right !=null)
foreach (T p in ScanPreorder (root.Right))
yield return p;
}
}
class IteratorPattern {
// Iterator Pattern for a Tree Judith Bishop September 2007
// Shows two enumerators using links and recursion
static void Main() {
var family = new Tree <Person> ( new Node <Person>
(new Person ("Tom", 1950),
new Node <Person> (new Person ("Peter", 1976),
new Node <Person>
(new Person ("Sarah", 2000), null,
new Node <Person>
(new Person ("James", 2002), null,
null)// no more siblings James
),
new Node <Person>
(new Person ("Robert", 1978), null,
new Node <Person>
(new Person ("Mark", 1980),
new Node <Person>
(new Person ("Carrie", 2005), null, null),
null)// no more siblings Mark
)),
null) // no siblings Tom
);
Console.WriteLine("Full family");
foreach (Person p in family.Preorder)
Console.Write(p+" ");
Console.WriteLine("\n");
// Older syntax
var selection = family.
Where(p=> p.Birth > 1980);
// New syntax
selection = from p in family
where p.Birth > 1980
orderby p.Name
select p;
Console.WriteLine("Born after 1980 in alpha order");
foreach (Person p in selection)
Console.Write(p+" ");
Console.WriteLine("\n");
}
}
using System;
using System.Collections.Generic;
using System.Collections;