CSharp: Adapter Pattern in donet core 3
/// <summary>
/// 适配器模式 Adapter PatternA
/// geovindu, Geovin Du edit
/// </summary>
interface IRectangle
{
void AboutMe();
}
/// <summary>
///
/// </summary>
class Rectangle : IRectangle
{
public void AboutMe()
{
Console.WriteLine("Actually, I am a Rectangle(三角形).");
}
}
/// <summary>
///
/// </summary>
interface ITriangle
{
void AboutTriangle();
}
/// <summary>
///
/// </summary>
class Triangle : ITriangle
{
public void AboutTriangle()
{
Console.WriteLine("Actually, I am a Triangle(矩形).");
}
}
/*
* RectangleAdapter is implementing IRectangle.
* So, it needs to implement all the methods
* defined in the target interface.
*/
/// <summary>
///
/// </summary>
class RectangleAdapter : Triangle, IRectangle
{
public void AboutMe()
{
//Invoking the adaptee method
//For Q&A
//Console.WriteLine("You are using an adapter now.");
AboutTriangle();
}
}
/// <summary>
/// 适配器模式 Adapter PatternA
/// geovindu, Geovin Du edit
/// </summary>
public interface ICommand
{
void Execute();
}
/// <summary>
///
/// </summary>
public class SaveCommand : ICommand
{
public void Execute()
{
Console.WriteLine("Saving current file");
}
}
/// <summary>
///
/// </summary>
public class OpenCommand : ICommand
{
public void Execute()
{
Console.WriteLine("Opening a file");
}
}
/// <summary>
///
/// </summary>
public class Button
{
private ICommand command;
private string name;
public Button(ICommand command, string name)
{
this.command = command;
this.name = name;
}
public void Click()
{
command.Execute();
}
public void PrintMe()
{
Console.WriteLine($"I am a button called {name}");
}
}
/// <summary>
///
/// </summary>
public class Editor
{
public IEnumerable<Button> Buttons { get; }
public Editor(IEnumerable<Button> buttons)
{
Buttons = buttons;
}
public void ClickAll()
{
foreach (var btn in Buttons)
{
btn.Click();
}
}
}
/// <summary>
/// 适配器模式 Adapter PatternA
/// geovindu, Geovin Du edit
/// </summary>
public interface IInteger
{
int Value { get; }
}
/// <summary>
///
/// </summary>
public static class Dimensions
{
public class Two : IInteger
{
public int Value => 2;
}
public class Three : IInteger
{
public int Value => 3;
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="TSelf"></typeparam>
/// <typeparam name="T"></typeparam>
/// <typeparam name="D"></typeparam>
public abstract class Vector<TSelf, T, D>
where D : IInteger, new()
where TSelf : Vector<TSelf, T, D>, new()
{
protected T[] data;
public Vector()
{
data = new T[new D().Value];
}
public Vector(params T[] values)
{
var requiredSize = new D().Value;
data = new T[requiredSize];
var providedSize = values.Length;
for (int i = 0; i < Math.Min(requiredSize, providedSize); ++i)
data[i] = values[i];
}
public static TSelf Create(params T[] values)
{
var result = new TSelf();
var requiredSize = new D().Value;
result.data = new T[requiredSize];
var providedSize = values.Length;
for (int i = 0; i < Math.Min(requiredSize, providedSize); ++i)
result.data[i] = values[i];
return result;
}
public T this[int index]
{
get => data[index];
set => data[index] = value;
}
public T X
{
get => data[0];
set => data[0] = value;
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="TSelf"></typeparam>
/// <typeparam name="D"></typeparam>
public class VectorOfFloat<TSelf, D>
: Vector<TSelf, float, D>
where D : IInteger, new()
where TSelf : Vector<TSelf, float, D>, new()
{
}
/// <summary>
///
/// </summary>
/// <typeparam name="D"></typeparam>
public class VectorOfInt<D> : Vector<VectorOfInt<D>, int, D>
where D : IInteger, new()
{
public VectorOfInt()
{
}
public VectorOfInt(params int[] values) : base(values)
{
}
public static VectorOfInt<D> operator +
(VectorOfInt<D> lhs, VectorOfInt<D> rhs)
{
var result = new VectorOfInt<D>();
var dim = new D().Value;
for (int i = 0; i < dim; i++)
{
result[i] = lhs[i] + rhs[i];
}
return result;
}
}
/// <summary>
///
/// </summary>
public class Vector2i : VectorOfInt<Dimensions.Two>
{
public Vector2i(params int[] values) : base(values)
{
}
}
/// <summary>
///
/// </summary>
public class Vector3f
: VectorOfFloat<Vector3f, Dimensions.Three>
{
public override string ToString()
{
return $"{string.Join(",", data)}";
}
}
/// <summary>
///
/// </summary>
public class CountryStats
{
[XmlIgnore]
public Dictionary<string, string> Capitals { get; set; }
= new Dictionary<string, string>();
public (string, string)[] CapitalsSerializable
{
get
{
return Capitals.Keys.Select(country =>
(country, Capitals[country])).ToArray();
}
set
{
Capitals = value.ToDictionary(x => x.Item1, x => x.Item2);
}
}
}
调用:
//适配器模式 Adapter Pattern
Console.WriteLine("***适配器模式 Adapter Pattern Alternative Implementation Technique Demo.***\n");
IRectangle rectangle = new Rectangle();
Console.WriteLine("For initial verification purposes, printing the details from of both shapes.");
Console.WriteLine("The rectangle.AboutMe() says:");
rectangle.AboutMe();
ITriangle triangle = new Triangle();
Console.WriteLine("The triangle.AboutTriangle() says:");
triangle.AboutTriangle();
Console.WriteLine("\nNow using the adapter.");
IRectangle adapter = new RectangleAdapter();
Console.Write("True fact : ");
adapter.AboutMe();
Console.WriteLine("*****************************");
//
// for each ICommand, a Button is created to wrap it, and all
// are passed to the editor
var b = new ContainerBuilder();
b.RegisterType<OpenCommand>()
.As<ICommand>()
.WithMetadata("Name", "Open");
b.RegisterType<SaveCommand>()
.As<ICommand>()
.WithMetadata("Name", "Save");
//b.RegisterType<Button>();
//b.RegisterAdapter<ICommand, Button>(cmd => new Button(cmd, ""));
b.RegisterAdapter<Meta<ICommand>, Button>(cmd =>
new Button(cmd.Value, (string)cmd.Metadata["Name"]));
b.RegisterType<Editor>();
using var c = b.Build();
var editor = c.Resolve<Editor>();
editor.ClickAll();
// problem: only one button
foreach (var btn in editor.Buttons)
btn.PrintMe();
//
var v = new Vector2i(1, 2);
v[0] = 0;
var vv = new Vector2i(3, 2);
var result = v + vv;
var u = Vector3f.Create(3.5f, 2.2f, 1);
Console.WriteLine(u.ToString());
//
var stats = new CountryStats();
stats.Capitals.Add("France", "Paris");
var xs = new XmlSerializer(typeof(CountryStats));
var stringBuilder = new StringBuilder();
var stringWriter = new StringWriter(stringBuilder);
xs.Serialize(stringWriter, stats);
//Clipboard.SetText(stringBuilder.ToString());
Console.WriteLine(stringBuilder.ToString());
var newStats = (CountryStats)xs.Deserialize(
new StringReader(stringWriter.ToString()));
Console.WriteLine(newStats.Capitals["France"]);
输出:
***适配器模式 Adapter Pattern Alternative Implementation Technique Demo.***
For initial verification purposes, printing the details from of both shapes.
The rectangle.AboutMe() says:
Actually, I am a Rectangle(三角形).
The triangle.AboutTriangle() says:
Actually, I am a Triangle(矩形).
Now using the adapter.
True fact : Actually, I am a Triangle(矩形).
*****************************
Opening a file
Saving current file
I am a button called Open
I am a button called Save
3.5,2.2,1
<?xml version="1.0" encoding="utf-16"?>
<CountryStats xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CapitalsSerializable>
<ValueTupleOfStringString>
<Item1>France</Item1>
<Item2>Paris</Item2>
</ValueTupleOfStringString>
</CapitalsSerializable>
</CountryStats>
Paris
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号