diff --git a/Finished sample/.editorconfig b/Finished sample/.editorconfig new file mode 100644 index 0000000..ddb2c49 --- /dev/null +++ b/Finished sample/.editorconfig @@ -0,0 +1,232 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary +dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = omit_if_default # I hate "private" everywhere! + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = false # see README for explanation +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:warning +dotnet_style_prefer_collection_expression = true +dotnet_style_prefer_compound_assignment = true +#Dick dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +#Dick dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = true +csharp_style_var_when_type_is_apparent = true + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true +#Dick csharp_style_expression_bodied_constructors = true +#Dick csharp_style_expression_bodied_indexers = true +#Dick csharp_style_expression_bodied_lambdas = true:suggestion +#Dick csharp_style_expression_bodied_local_functions = true:suggestion +#Dick csharp_style_expression_bodied_methods = true +#Dick csharp_style_expression_bodied_operators = true +#Dick csharp_style_expression_bodied_properties = true + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_style_namespace_declarations = file_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_top_level_statements = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +dotnet_diagnostic.IDE0058.severity = none +#Dick csharp_style_unused_value_assignment_preference = discard_variable +#Dick charp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/Finished sample/AbstractFactory/Implementation.cs b/Finished sample/AbstractFactory/Implementation.cs index 6e71024..e0b27f4 100644 --- a/Finished sample/AbstractFactory/Implementation.cs +++ b/Finished sample/AbstractFactory/Implementation.cs @@ -1,118 +1,100 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace AbstractFactory; -namespace AbstractFactory +/// +/// AbstractFactory +/// +public interface IShoppingCartPurchaseFactory { - /// - /// AbstractFactory - /// - public interface IShoppingCartPurchaseFactory - { - IDiscountService CreateDiscountService(); - IShippingCostsService CreateShippingCostsService(); - } - - /// - /// AbstractProduct - /// - public interface IDiscountService - { - int DiscountPercentage { get; } - } - - /// - /// ConcreteProduct - /// - public class BelgiumDiscountService : IDiscountService - { - public int DiscountPercentage => 20; - } + IDiscountService CreateDiscountService(); + IShippingCostsService CreateShippingCostsService(); +} - /// - /// ConcreteProduct - /// - public class FranceDiscountService : IDiscountService - { - public int DiscountPercentage => 10; - } +/// +/// AbstractProduct +/// +public interface IDiscountService +{ + int DiscountPercentage { get; } +} - /// - /// AbstractProduct - /// - public interface IShippingCostsService - { - decimal ShippingCosts { get; } - } +/// +/// ConcreteProduct +/// +public class BelgiumDiscountService : IDiscountService +{ + public int DiscountPercentage => 20; +} - /// - /// ConcreteProduct - /// - public class BelgiumShippingCostsService : IShippingCostsService - { - public decimal ShippingCosts => 20; - } +/// +/// ConcreteProduct +/// +public class FranceDiscountService : IDiscountService +{ + public int DiscountPercentage => 10; +} - /// - /// ConcreteProduct - /// - public class FranceShippingCostsService : IShippingCostsService - { - public decimal ShippingCosts => 25; - } +/// +/// AbstractProduct +/// +public interface IShippingCostsService +{ + decimal ShippingCosts { get; } +} +/// +/// ConcreteProduct +/// +public class BelgiumShippingCostsService : IShippingCostsService +{ + public decimal ShippingCosts => 20; +} - public class BelgiumShoppingCartPurchaseFactory : IShoppingCartPurchaseFactory - { - public IDiscountService CreateDiscountService() - { - return new BelgiumDiscountService(); - } +/// +/// ConcreteProduct +/// +public class FranceShippingCostsService : IShippingCostsService +{ + public decimal ShippingCosts => 25; +} - public IShippingCostsService CreateShippingCostsService() - { - return new BelgiumShippingCostsService(); - } - } +/// +/// ConcreteFactory +/// +public class BelgiumShoppingCartPurchaseFactory : IShoppingCartPurchaseFactory +{ + public IDiscountService CreateDiscountService() => new BelgiumDiscountService(); + public IShippingCostsService CreateShippingCostsService() => new BelgiumShippingCostsService(); +} - public class FranceShoppingCartPurchaseFactory : IShoppingCartPurchaseFactory - { - public IDiscountService CreateDiscountService() - { - return new FranceDiscountService(); - } +/// +/// ConcreteFactory +/// +public class FranceShoppingCartPurchaseFactory : IShoppingCartPurchaseFactory +{ + public IDiscountService CreateDiscountService() => new FranceDiscountService(); - public IShippingCostsService CreateShippingCostsService() - { - return new FranceShippingCostsService(); - } - } + public IShippingCostsService CreateShippingCostsService() => new FranceShippingCostsService(); +} +/// +/// Client class +/// +public class ShoppingCart +{ + readonly IDiscountService _discountService; + readonly IShippingCostsService _shippingCostsService; + readonly int _orderCosts; - /// - /// Client class - /// - public class ShoppingCart + // Constructor + public ShoppingCart(IShoppingCartPurchaseFactory factory) { - private readonly IDiscountService _discountService; - private readonly IShippingCostsService _shippingCostsService; - private int _orderCosts; - - // Constructor - public ShoppingCart(IShoppingCartPurchaseFactory factory) - { - _discountService = factory.CreateDiscountService(); - _shippingCostsService = factory.CreateShippingCostsService(); - // assume that the total cost of all the items we ordered = 200 euro - _orderCosts = 200; - } + _discountService = factory.CreateDiscountService(); + _shippingCostsService = factory.CreateShippingCostsService(); + // assume that the total cost of all the items we ordered = 200 euro + _orderCosts = 200; + } - public void CalculateCosts() - { - Console.WriteLine($"Total costs = {_orderCosts - (_orderCosts / 100 * _discountService.DiscountPercentage) + _shippingCostsService.ShippingCosts }"); - } - } + public void CalculateCosts() => Console.WriteLine("Total costs = " + + $"{_orderCosts - _orderCosts / 100 * _discountService.DiscountPercentage + _shippingCostsService.ShippingCosts}"); } diff --git a/Finished sample/AbstractFactory/Program.cs b/Finished sample/AbstractFactory/Program.cs index db3730d..f88bd2a 100644 --- a/Finished sample/AbstractFactory/Program.cs +++ b/Finished sample/AbstractFactory/Program.cs @@ -1,5 +1,7 @@ using AbstractFactory; +Console.Title = "Abstract Factory"; + var belgiumShoppingCartPurchaseFactory = new BelgiumShoppingCartPurchaseFactory(); var shoppingCartForBelgium = new ShoppingCart(belgiumShoppingCartPurchaseFactory); shoppingCartForBelgium.CalculateCosts(); @@ -7,5 +9,5 @@ var franceShoppingCartPurchaseFactory = new FranceShoppingCartPurchaseFactory(); var shoppingCartForFrance = new ShoppingCart(franceShoppingCartPurchaseFactory); shoppingCartForFrance.CalculateCosts(); - -Console.ReadKey(); \ No newline at end of file + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Adapter/ClassAdapterImplementation.cs b/Finished sample/Adapter/ClassAdapterImplementation.cs index 89a61b4..c7d6c0b 100644 --- a/Finished sample/Adapter/ClassAdapterImplementation.cs +++ b/Finished sample/Adapter/ClassAdapterImplementation.cs @@ -1,70 +1,61 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace ClassAdapter; -namespace Adapter.ClassAdapter +public class CityFromExternalSystem { - public class CityFromExternalSystem - { - public string Name { get; private set; } - public string NickName { get; private set; } - public int Inhabitants { get; private set; } - - public CityFromExternalSystem(string name, string nickName, int inhabitants) - { - Name = name; - NickName = nickName; - Inhabitants = inhabitants; - } - } + public string Name { get; } + public string NickName { get; } + public int Inhabitants { get; } - /// - /// Adaptee - /// - public class ExternalSystem + public CityFromExternalSystem(string name, string nickName, int inhabitants) { - public CityFromExternalSystem GetCity() - { - return new CityFromExternalSystem("Antwerp", "'t Stad", 500000); - } + Name = name; + NickName = nickName; + Inhabitants = inhabitants; } +} - public class City - { - public string FullName { get; private set; } - public long Inhabitants { get; private set; } +/// +/// Adaptee +/// +public class ExternalSystem +{ + public CityFromExternalSystem GetCity() => + new("Antwerp", "'t Stad", 500000); +} - public City(string fullName, long inhabitants) - { - FullName = fullName; - Inhabitants = inhabitants; - } - } +public class City +{ + public string FullName { get; } + public long Inhabitants { get; } - /// - /// Target - /// - public interface ICityAdapter + public City(string fullName, long inhabitants) { - City GetCity(); + FullName = fullName; + Inhabitants = inhabitants; } +} - /// - /// Adapter - /// - public class CityAdapter : ExternalSystem, ICityAdapter - { - public City GetCity() - { - // call into the external system - var cityFromExternalSystem = base.GetCity(); +/// +/// Target +/// +public interface ICityAdapter +{ + City GetCity(); +} + +/// +/// Adapter +/// +public class CityAdapter : ExternalSystem, ICityAdapter +{ + public new City GetCity() + { + // call into the external system + CityFromExternalSystem cityFromExternalSystem = base.GetCity(); - // adapt the CityFromExternalCity to a City - return new City( - $"{cityFromExternalSystem.Name} - {cityFromExternalSystem.NickName}" - , cityFromExternalSystem.Inhabitants); - } + // adapt the CityFromExternalCity to a City + return new City( + $"{cityFromExternalSystem.Name} - {cityFromExternalSystem.NickName}" + , cityFromExternalSystem.Inhabitants); } } diff --git a/Finished sample/Adapter/ObjectAdapterImplementation.cs b/Finished sample/Adapter/ObjectAdapterImplementation.cs index 9b12393..7d6877c 100644 --- a/Finished sample/Adapter/ObjectAdapterImplementation.cs +++ b/Finished sample/Adapter/ObjectAdapterImplementation.cs @@ -1,75 +1,66 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Adapter; -namespace Adapter.ObjectAdapter +public class CityFromExternalSystem { - public class CityFromExternalSystem - { - public string Name { get; private set; } - public string NickName { get; private set; } - public int Inhabitants { get; private set; } - - public CityFromExternalSystem( - string name, - string nickName, - int inhabitants) - { - Name = name; - NickName = nickName; - Inhabitants = inhabitants; - } - } + public string Name { get; } + public string NickName { get; } + public int Inhabitants { get; } - /// - /// Adaptee - /// - public class ExternalSystem + public CityFromExternalSystem( + string name, + string nickName, + int inhabitants) { - public CityFromExternalSystem GetCity() - { - return new CityFromExternalSystem("Antwerp", "'t Stad", 500000); - } + Name = name; + NickName = nickName; + Inhabitants = inhabitants; } +} - public class City - { - public string FullName { get; private set; } - public long Inhabitants { get; private set; } +/// +/// Adaptee +/// +public class ExternalSystem +{ + public CityFromExternalSystem GetCity() => + new("Antwerp", "'t Stad", 500000); +} - public City(string fullName, long inhabitants) - { - FullName = fullName; - Inhabitants = inhabitants; - } - } +public class City +{ + public string FullName { get; } + public long Inhabitants { get; } - /// - /// Target - /// - public interface ICityAdapter + public City(string fullName, long inhabitants) { - City GetCity(); + FullName = fullName; + Inhabitants = inhabitants; } +} - /// - /// Adapter - /// - public class CityAdapter : ICityAdapter - { - public ExternalSystem ExternalSystem { get; private set; } = new(); +/// +/// Target +/// +public interface ICityAdapter +{ + City GetCity(); +} - public City GetCity() - { - // call into the external system - var cityFromExternalSystem = ExternalSystem.GetCity(); +/// +/// Adapter +/// +public class CityAdapter : ICityAdapter +{ + public ExternalSystem ExternalSystem { get; } = new(); + + public City GetCity() + { + // call into the external system + CityFromExternalSystem cityFromExternalSystem = ExternalSystem.GetCity(); - // adapt the CityFromExternalCity to a City - return new City( - $"{cityFromExternalSystem.Name} - {cityFromExternalSystem.NickName}" - , cityFromExternalSystem.Inhabitants); - } - } + // adapt the CityFromExternalCity to a City + return new City( + $"{cityFromExternalSystem.Name} - {cityFromExternalSystem.NickName}" + , cityFromExternalSystem.Inhabitants); + } } diff --git a/Finished sample/Adapter/Program.cs b/Finished sample/Adapter/Program.cs index 367335c..0142bda 100644 --- a/Finished sample/Adapter/Program.cs +++ b/Finished sample/Adapter/Program.cs @@ -1,9 +1,10 @@ -using Adapter; -using Adapter.ClassAdapter; +using ClassAdapter; + +Console.Title = "Adapter"; // adapter example (same code for object & class adapter) ICityAdapter adapter = new CityAdapter(); -var city = adapter.GetCity(); +City city = adapter.GetCity(); Console.WriteLine($"{city.FullName}, {city.Inhabitants}"); -Console.ReadKey(); \ No newline at end of file +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Bridge/Implementation.cs b/Finished sample/Bridge/Implementation.cs index 1803397..1674585 100644 --- a/Finished sample/Bridge/Implementation.cs +++ b/Finished sample/Bridge/Implementation.cs @@ -1,85 +1,65 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Bridge; -namespace Bridge +/// +/// Abstraction +/// +public abstract class Menu { - /// - /// Abstraction - /// - public abstract class Menu - { - public readonly ICoupon _coupon; - public abstract int CalculatePrice(); - - public Menu(ICoupon coupon) - { - _coupon = coupon; - } - } - - - /// - /// RefinedAbstraction - /// - public class VegetarianMenu : Menu - { - public VegetarianMenu(ICoupon coupon): base(coupon) - { - } - public override int CalculatePrice() - { - return 20 - _coupon.CouponValue; - } - } + public readonly ICoupon _coupon = null!; + public abstract int CalculatePrice(); + protected Menu(ICoupon coupon) => _coupon = coupon; +} - /// - /// RefinedAbstraction - /// - public class MeatBasedMenu : Menu +/// +/// RefinedAbstraction +/// +public class VegetarianMenu : Menu +{ + public VegetarianMenu(ICoupon coupon) : base(coupon) { - public MeatBasedMenu(ICoupon coupon) : base(coupon) - { - } - public override int CalculatePrice() - { - return 30 - _coupon.CouponValue; - } } + public override int CalculatePrice() => 20 - _coupon.CouponValue; +} - - /// - /// Implementor - /// - public interface ICoupon +/// +/// RefinedAbstraction +/// +public class MeatBasedMenu : Menu +{ + public MeatBasedMenu(ICoupon coupon) : base(coupon) { - int CouponValue { get; } } + public override int CalculatePrice() => 30 - _coupon.CouponValue; +} +/// +/// Implementor +/// +public interface ICoupon +{ + int CouponValue { get; } +} - /// - /// ConcreteImplementor - /// - public class NoCoupon : ICoupon - { - public int CouponValue { get => 0; } - } +/// +/// ConcreteImplementor +/// +public class NoCoupon : ICoupon +{ + public int CouponValue => 0; +} - /// - /// ConcreteImplementor - /// - public class OneEuroCoupon : ICoupon - { - public int CouponValue { get => 1; } - } +/// +/// ConcreteImplementor +/// +public class OneEuroCoupon : ICoupon +{ + public int CouponValue => 1; +} - /// - /// ConcreteImplementor - /// - public class TwoEuroCoupon : ICoupon - { - public int CouponValue { get => 2; } - } +/// +/// ConcreteImplementor +/// +public class TwoEuroCoupon : ICoupon +{ + public int CouponValue => 2; } \ No newline at end of file diff --git a/Finished sample/Bridge/Program.cs b/Finished sample/Bridge/Program.cs index beb8ebd..ac2a862 100644 --- a/Finished sample/Bridge/Program.cs +++ b/Finished sample/Bridge/Program.cs @@ -1,6 +1,6 @@ -// create a menu implementation +using Bridge; -using Bridge; +Console.Title = "Bridge"; var noCoupon = new NoCoupon(); var oneEuroCoupon = new OneEuroCoupon(); @@ -16,5 +16,5 @@ vegetarianMenu = new VegetarianMenu(oneEuroCoupon); Console.WriteLine($"Vegetarian menu, one euro coupon: {vegetarianMenu.CalculatePrice()} euro."); - + Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Builder/Implementation.cs b/Finished sample/Builder/Implementation.cs index 1aae5a5..18a4dd0 100644 --- a/Finished sample/Builder/Implementation.cs +++ b/Finished sample/Builder/Implementation.cs @@ -1,216 +1,97 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Text; -namespace BuilderPattern -{ +namespace BuilderPattern; +/// +/// Product +/// +public class Car +{ + readonly List _parts = new(); + readonly string _carType; - /// - /// Director - /// - public class Garage - { - private CarBuilder? _builder; - - public Garage() - { - } + public Car(string carType) => _carType = carType; - public void Construct(CarBuilder builder) - { - _builder = builder; - - _builder.BuildEngine(); - _builder.BuildFrame(); - } + public void AddPart(string part) => _parts.Add(part); - // variation: the show method on the director instead of on the product. - public void Show() - { - Console.WriteLine(_builder?.Car.ToString()); - } - } - - /// - /// Builder abstract class - /// - public abstract class CarBuilder + public override string ToString() { - public Car Car { get; private set; } - - public CarBuilder(string carType) - { - Car = new Car(carType); - } - public abstract void BuildEngine(); - public abstract void BuildFrame(); - } - - /// - /// ConcreteBuilder1 class - /// - public class MiniBuilder : CarBuilder - { - public MiniBuilder() - : base("Mini") + var sb = new StringBuilder(); + foreach (var part in _parts) { + sb.Append("Car of type ") + .Append(_carType) + .Append(" has part ") + .Append(part) + .Append(". "); } - public override void BuildEngine() - { - Car.AddPart("'not a V8'"); - } - - public override void BuildFrame() - { - Car.AddPart("'3-door with stripes'"); - } + return sb.ToString(); } +} - /// - /// ConcreteBuilder2 class - /// - public class BMWBuilder : CarBuilder - { - // Invoke base class constructor - public BMWBuilder() - : base("BMW") - { - } +/// +/// Builder +/// +public abstract class CarBuilder +{ + public Car Car { get; } - public override void BuildEngine() - { - Car.AddPart("'a fancy V8 engine'"); - } + protected CarBuilder(string carType) => Car = new Car(carType); - public override void BuildFrame() - { - Car.AddPart("'5-door with metallic finish'"); - } - } - + public abstract void BuildEngine(); + public abstract void BuildFrame(); +} - /// - /// Product class - /// - public class Car +/// +/// ConcreteBuilder1 class +/// +public class MiniBuilder : CarBuilder +{ + public MiniBuilder() + : base("Mini") { - private readonly List _parts = new(); - private readonly string _carType; - - public Car(string carType) - { - _carType = carType; - } - - public void AddPart(string part) - { - _parts.Add(part); - } - - public override string ToString() - { - var sb = new StringBuilder(); - foreach (string part in _parts) - { - sb.Append($"Car of type {_carType} has part {part}. "); - } - - return sb.ToString(); - } - } - + } + public override void BuildEngine() => Car.AddPart("'not a V8'"); - /// - /// The 'Director' class - /// - public class Director - { - // Builder uses a complex series of steps - public void Construct(Builder builder) - { - builder.BuildPartA(); - builder.BuildPartB(); - } - } + public override void BuildFrame() => Car.AddPart("'3-door with stripes'"); +} - /// - /// The 'Builder' abstract class - /// - public abstract class Builder +/// +/// ConcreteBuilder2 class +/// +public class BMWBuilder : CarBuilder +{ + // Invoke base class constructor + public BMWBuilder() + : base("BMW") { - public abstract void BuildPartA(); - public abstract void BuildPartB(); - public abstract Product GetResult(); } - /// - /// The 'ConcreteBuilder1' class - /// - public class ConcreteBuilder1 : Builder - { - private Product product = new Product(); - - public override void BuildPartA() - { - product.Add("PartA"); - } + public override void BuildEngine() => Car.AddPart("'a fancy V8 engine'"); - public override void BuildPartB() - { - product.Add("PartB"); - } + public override void BuildFrame() => Car.AddPart("'5-door with metallic finish'"); +} - public override Product GetResult() - { - return product; - } - } +/// +/// Director +/// +public class Garage +{ + CarBuilder? _builder; - /// - /// The 'ConcreteBuilder2' class - /// - public class ConcreteBuilder2 : Builder + public Garage() { - private Product product = new Product(); - - public override void BuildPartA() - { - product.Add("PartX"); - } - - public override void BuildPartB() - { - product.Add("PartY"); - } - - public override Product GetResult() - { - return product; - } } - /// - /// The 'Product' class - /// - public class Product + public void Construct(CarBuilder builder) { - private List parts = new List(); + _builder = builder; - public void Add(string part) - { - parts.Add(part); - } - - public void Show() - { - Console.WriteLine("\nProduct Parts -------"); - foreach (string part in parts) - Console.WriteLine(part); - } + _builder.BuildEngine(); + _builder.BuildFrame(); } + + public void Show() => Console.WriteLine(_builder?.Car.ToString()); } diff --git a/Finished sample/Builder/Program.cs b/Finished sample/Builder/Program.cs index 47802f5..2a5ce85 100644 --- a/Finished sample/Builder/Program.cs +++ b/Finished sample/Builder/Program.cs @@ -1,22 +1,6 @@ using BuilderPattern; - -//Director director = new Director(); - -//Builder b1 = new ConcreteBuilder1(); -//Builder b2 = new ConcreteBuilder2(); - -//// Construct two products -//director.Construct(b1); -//Product p1 = b1.GetResult(); -//p1.Show(); - -//director.Construct(b2); -//Product p2 = b2.GetResult(); -//p2.Show(); - - - +Console.Title = "Builder"; var garage = new Garage(); @@ -32,5 +16,5 @@ Console.WriteLine(bmwBuilder.Car.ToString()); // or: garage.Show(); - + Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/ChainOfResponsibility/Implementation.cs b/Finished sample/ChainOfResponsibility/Implementation.cs index 9f76837..35e38bf 100644 --- a/Finished sample/ChainOfResponsibility/Implementation.cs +++ b/Finished sample/ChainOfResponsibility/Implementation.cs @@ -1,149 +1,148 @@ using System.ComponentModel.DataAnnotations; -namespace ChainOfResponsibility +namespace ChainOfResponsibility; + +public class Document { - public class Document + public string Title { get; set; } + public DateTimeOffset LastModified { get; set; } + public bool ApprovedByLitigation { get; set; } + public bool ApprovedByManagement { get; set; } + + public Document( + string title, + DateTimeOffset lastModified, + bool approvedByLitigation, + bool approvedByManagement) { - public string Title { get; set; } - public DateTimeOffset LastModified { get; set; } - public bool ApprovedByLitigation { get; set; } - public bool ApprovedByManagement { get; set; } - - public Document( - string title, - DateTimeOffset lastModified, - bool approvedByLitigation, - bool approvedByManagement) - { - Title = title; - LastModified = lastModified; - ApprovedByLitigation = approvedByLitigation; - ApprovedByManagement = approvedByManagement; - } + Title = title; + LastModified = lastModified; + ApprovedByLitigation = approvedByLitigation; + ApprovedByManagement = approvedByManagement; } +} - /// - /// Handler - /// - public interface IHandler where T : class - { - IHandler SetSuccessor(IHandler successor); - void Handle(T request); - } +/// +/// Handler +/// +public interface IHandler where T : class +{ + IHandler SetSuccessor(IHandler successor); + void Handle(T request); +} + +/// +/// ConcreteHandler +/// +public class DocumentTitleHandler : IHandler +{ + IHandler? _successor; - /// - /// ConcreteHandler - /// - public class DocumentTitleHandler : IHandler + public void Handle(Document document) { - private IHandler? _successor; - - public void Handle(Document document) + if (document.Title.Length == 0) { - if (document.Title == string.Empty) - { - // validation doesn't check out - throw new ValidationException( - new ValidationResult( - "Title must be filled out", - new List() { "Title" }), null, null); - } - - // go to the next handler - _successor?.Handle(document); + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Title must be filled out", + new List() { "Title" }), null, null); } - public IHandler SetSuccessor(IHandler successor) - { - _successor = successor; - return successor; - } + // go to the next handler + _successor?.Handle(document); } - /// - /// ConcreteHandler - /// - public class DocumentLastModifiedHandler : IHandler + public IHandler SetSuccessor(IHandler successor) { - private IHandler? _successor; + _successor = successor; + return successor; + } +} - public void Handle(Document document) - { - if (document.LastModified < DateTime.UtcNow.AddDays(-30)) - { - // validation doesn't check out - throw new ValidationException( - new ValidationResult( - "Document must be modified in the last 30 days", - new List() { "LastModified" }), null, null); - } - - // go to the next handler - _successor?.Handle(document); - } +/// +/// ConcreteHandler +/// +public class DocumentLastModifiedHandler : IHandler +{ + IHandler? _successor; - public IHandler SetSuccessor(IHandler successor) + public void Handle(Document document) + { + if (document.LastModified < DateTime.UtcNow.AddDays(-30)) { - _successor = successor; - return successor; + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Document must be modified in the last 30 days", + new List() { "LastModified" }), null, null); } + + // go to the next handler + _successor?.Handle(document); } - /// - /// ConcreteHandler - /// - public class DocumentApprovedByLitigationHandler : IHandler + public IHandler SetSuccessor(IHandler successor) { - private IHandler? _successor; + _successor = successor; + return successor; + } +} - public void Handle(Document document) - { - if (!document.ApprovedByLitigation) - { - // validation doesn't check out - throw new ValidationException( - new ValidationResult( - "Document must be approved by litigation", - new List() { "ApprovedByLitigation" }), null, null); - } - - // go to the next handler - _successor?.Handle(document); - } +/// +/// ConcreteHandler +/// +public class DocumentApprovedByLitigationHandler : IHandler +{ + IHandler? _successor; - public IHandler SetSuccessor(IHandler successor) + public void Handle(Document document) + { + if (!document.ApprovedByLitigation) { - _successor = successor; - return successor; + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Document must be approved by litigation", + new List() { "ApprovedByLitigation" }), null, null); } + + // go to the next handler + _successor?.Handle(document); } - /// - /// ConcreteHandler - /// - public class DocumentApprovedByManagementHandler : IHandler + public IHandler SetSuccessor(IHandler successor) { - private IHandler? _successor; + _successor = successor; + return successor; + } +} - public void Handle(Document document) - { - if (!document.ApprovedByManagement) - { - // validation doesn't check out - throw new ValidationException( - new ValidationResult( - "Document must be approved by management", - new List() { "ApprovedByManagement" }), null, null); - } - - // go to the next handler - _successor?.Handle(document); - } +/// +/// ConcreteHandler +/// +public class DocumentApprovedByManagementHandler : IHandler +{ + IHandler? _successor; - public IHandler SetSuccessor(IHandler successor) + public void Handle(Document document) + { + if (!document.ApprovedByManagement) { - _successor = successor; - return successor; + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Document must be approved by management", + new List() { "ApprovedByManagement" }), null, null); } + + // go to the next handler + _successor?.Handle(document); + } + + public IHandler SetSuccessor(IHandler successor) + { + _successor = successor; + return successor; } } \ No newline at end of file diff --git a/Finished sample/ChainOfResponsibility/Implementation.cs.bak b/Finished sample/ChainOfResponsibility/Implementation.cs.bak new file mode 100644 index 0000000..200818b --- /dev/null +++ b/Finished sample/ChainOfResponsibility/Implementation.cs.bak @@ -0,0 +1,148 @@ +using System.ComponentModel.DataAnnotations; + +namespace ChainOfResponsibility; + +public class Document +{ + public string Title { get; set; } + public DateTimeOffset LastModified { get; set; } + public bool ApprovedByLitigation { get; set; } + public bool ApprovedByManagement { get; set; } + + public Document( + string title, + DateTimeOffset lastModified, + bool approvedByLitigation, + bool approvedByManagement) + { + Title = title; + LastModified = lastModified; + ApprovedByLitigation = approvedByLitigation; + ApprovedByManagement = approvedByManagement; + } +} + +/// +/// Handler +/// +public interface IHandler where T : class +{ + IHandler SetSuccessor(IHandler successor); + void Handle(T request); +} + +/// +/// ConcreteHandler +/// +public class DocumentTitleHandler : IHandler +{ + IHandler? _successor; + + public void Handle(Document document) + { + if (document.Title?.Length == 0) + { + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Title must be filled out", + new List() { "Title" }), null, null); + } + + // go to the next handler + _successor?.Handle(document); + } + + public IHandler SetSuccessor(IHandler successor) + { + _successor = successor; + return successor; + } +} + +/// +/// ConcreteHandler +/// +public class DocumentLastModifiedHandler : IHandler +{ + IHandler? _successor; + + public void Handle(Document document) + { + if (document.LastModified < DateTime.UtcNow.AddDays(-30)) + { + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Document must be modified in the last 30 days", + new List() { "LastModified" }), null, null); + } + + // go to the next handler + _successor?.Handle(document); + } + + public IHandler SetSuccessor(IHandler successor) + { + _successor = successor; + return successor; + } +} + +/// +/// ConcreteHandler +/// +public class DocumentApprovedByLitigationHandler : IHandler +{ + IHandler? _successor; + + public void Handle(Document document) + { + if (!document.ApprovedByLitigation) + { + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Document must be approved by litigation", + new List() { "ApprovedByLitigation" }), null, null); + } + + // go to the next handler + _successor?.Handle(document); + } + + public IHandler SetSuccessor(IHandler successor) + { + _successor = successor; + return successor; + } +} + +/// +/// ConcreteHandler +/// +public class DocumentApprovedByManagementHandler : IHandler +{ + IHandler? _successor; + + public void Handle(Document document) + { + if (!document.ApprovedByManagement) + { + // validation doesn't check out + throw new ValidationException( + new ValidationResult( + "Document must be approved by management", + new List() { "ApprovedByManagement" }), null, null); + } + + // go to the next handler + _successor?.Handle(document); + } + + public IHandler SetSuccessor(IHandler successor) + { + _successor = successor; + return successor; + } +} \ No newline at end of file diff --git a/Finished sample/ChainOfResponsibility/Program.cs b/Finished sample/ChainOfResponsibility/Program.cs index 63a62fb..4964c64 100644 --- a/Finished sample/ChainOfResponsibility/Program.cs +++ b/Finished sample/ChainOfResponsibility/Program.cs @@ -1,12 +1,13 @@ -using ChainOfResponsibility; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; +using ChainOfResponsibility; -var validDocument = new Document("How to Avoid Java Development", +Console.Title = "Chain of Responsibility"; + +var validDocument = new Document("How to Avoid Java Development", DateTimeOffset.UtcNow, true, true); -var invalidDocument = new Document("How to Avoid Java Development", +var invalidDocument = new Document("How to Avoid Java Development", DateTimeOffset.UtcNow, false, true); -// chain a set of handlers var documentHandlerChain = new DocumentTitleHandler(); documentHandlerChain .SetSuccessor(new DocumentLastModifiedHandler()) @@ -23,4 +24,6 @@ catch (ValidationException validationException) { Console.WriteLine(validationException.Message); -} \ No newline at end of file +} + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Command/Implementation.cs b/Finished sample/Command/Implementation.cs index f4d303e..e5b42bd 100644 --- a/Finished sample/Command/Implementation.cs +++ b/Finished sample/Command/Implementation.cs @@ -1,198 +1,178 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Command; -namespace Command +public class Employee { - /// - /// ICommand - /// - public interface ICommand + public int Id { get; set; } + public string Name { get; set; } + + public Employee(int id, string name) { - void Execute(); - bool CanExecute(); - void Undo(); + Id = id; + Name = name; } - - /// - /// ConcreteCommand - /// - public class AddEmployeeToManagerList : ICommand +} +public class Manager : Employee +{ + public List Employees = new(); + public Manager(int id, string name) + : base(id, name) { - private readonly IEmployeeManagerRepository _employeeManagerRepository; - private readonly int _managerId; - private readonly Employee? _employee; - - public AddEmployeeToManagerList( - IEmployeeManagerRepository employeeManagerRepository, - int managerId, - Employee? employee) - { - _employeeManagerRepository = employeeManagerRepository; - _managerId = managerId; - _employee = employee; - } + } +} - public bool CanExecute() - { - // potentially check against business/technical rules that might block execution +/// +/// Receiver (interface) +/// +public interface IEmployeeManagerRepository +{ + void AddEmployee(int managerId, Employee employee); + void RemoveEmployee(int managerId, Employee employee); + bool HasEmployee(int managerId, int employeeId); + void WriteDataStore(); +} + +/// +/// Receiver (implementation) +/// +public class EmployeeManagerRepository : IEmployeeManagerRepository +{ + // for demo purposes, use an in-memory datastore as a fake "manager list" + readonly List _managers = new() + { new Manager(1, "Katie"), new Manager(2, "Geoff") }; - // employee shouldn't be null - if (_employee == null) - { - return false; - } + public void AddEmployee(int managerId, Employee employee) => + // in real-life, add additional input & error checks + _managers.First(m => m.Id == managerId).Employees.Add(employee); - // employee shouldn't be on the manager's list already - if (_employeeManagerRepository.HasEmployee(_managerId, _employee.Id)) - { - return false; - } + public void RemoveEmployee(int managerId, Employee employee) => + // in real-life, add additional input & error checks + _managers.First(m => m.Id == managerId).Employees.Remove(employee); - // other potential rule(s): ensure that an employee can only be added to - // one manager's list at the same time, etc. - return true; - } + public bool HasEmployee(int managerId, int employeeId) => + // in real-life, add additional input & error checks + _managers.First(m => m.Id == managerId) + .Employees.Any(e => e.Id == employeeId); - public void Execute() + /// + /// For demo purposes, write out the data store to the console window + /// + public void WriteDataStore() + { + foreach (Manager manager in _managers) { - if (_employee == null) + Console.WriteLine($"Manager {manager.Id}, {manager.Name}"); + if (manager.Employees.Any()) { - return; + foreach (Employee employee in manager.Employees) + { + Console.WriteLine($"\t Employee {employee.Id}, {employee.Name}"); + } } - - _employeeManagerRepository.AddEmployee(_managerId, _employee); - } - - public void Undo() - { - if (_employee == null) + else { - return; + Console.WriteLine("\t No employees."); } - - _employeeManagerRepository.RemoveEmployee(_managerId, _employee); } } +} - /// - /// Invoker - /// - public class CommandManager +/// +/// Command +/// +public interface ICommand +{ + void Execute(); + bool CanExecute(); + void Undo(); +} + +/// +/// ConcreteCommand +/// +public class AddEmployeeToManagerList : ICommand +{ + readonly IEmployeeManagerRepository _employeeManagerRepository; + readonly int _managerId; + readonly Employee? _employee; + + public AddEmployeeToManagerList( + IEmployeeManagerRepository employeeManagerRepository, + int managerId, + Employee? employee) { - private readonly Stack _commands = new Stack(); + _employeeManagerRepository = employeeManagerRepository; + _managerId = managerId; + _employee = employee; + } - public void Invoke(ICommand command) + public bool CanExecute() + { + // employee shouldn't be null + if (_employee == null) { - if (command.CanExecute()) - { - command.Execute(); - _commands.Push(command); - } + return false; } - public void Undo() + // employee shouldn't be on the manager's list already + if (_employeeManagerRepository.HasEmployee(_managerId, _employee.Id)) { - if (_commands.Any()) - { - _commands.Pop()?.Undo(); - } + return false; } - public void UndoAll() - { - while (_commands.Any()) - { - _commands.Pop()?.Undo(); - } - } + // other potential rule(s): ensure that an employee can only be added to + // one manager's list at the same time, etc. + return true; } - - - public class Employee + public void Execute() { - public int Id { get; set; } - public string Name { get; set; } - - public Employee(int id, string name) + if (_employee == null) { - Id = id; - Name = name; + return; } + _employeeManagerRepository.AddEmployee(_managerId, _employee); } - public class Manager : Employee + public void Undo() { - public List Employees = new(); - public Manager(int id, string name) - : base(id, name) + if (_employee == null) { + return; } - } - /// - /// Receiver (interface) - /// - public interface IEmployeeManagerRepository - { - void AddEmployee(int managerId, Employee employee); - void RemoveEmployee(int managerId, Employee employee); - bool HasEmployee(int managerId, int employeeId); - void WriteDataStore(); + _employeeManagerRepository.RemoveEmployee(_managerId, _employee); } +} - /// - /// Receiver (implementation) - /// - public class EmployeeManagerRepository : IEmployeeManagerRepository - { - // for demo purposes, use an in-memory datastore as a fake "manager list" - private List _managers = new List() - { new Manager(1, "Katie"), new Manager(2, "Geoff") }; - - public void AddEmployee(int managerId, Employee employee) - { - // in real-life, add additional input & error checks - _managers.First(m => m.Id == managerId).Employees.Add(employee); - } +/// +/// Invoker +/// +public class CommandManager +{ + readonly Stack _commands = new(); - public void RemoveEmployee(int managerId, Employee employee) + public void Invoke(ICommand command) + { + if (command.CanExecute()) { - // in real-life, add additional input & error checks - _managers.First(m => m.Id == managerId).Employees.Remove(employee); + command.Execute(); + _commands.Push(command); } + } - public bool HasEmployee(int managerId, int employeeId) + public void Undo() + { + if (_commands.TryPop(out ICommand? cmd)) { - // in real-life, add additional input & error checks - return _managers.First(m => m.Id == managerId).Employees.Any(e => e.Id == employeeId); + cmd.Undo(); } + } - - /// - /// For demo purposes, write out the data store to the console window - /// - public void WriteDataStore() + public void UndoAll() + { + while (_commands.TryPop(out ICommand? cmd)) { - foreach (var manager in _managers) - { - Console.WriteLine($"Manager {manager.Id}, {manager.Name}"); - if (manager.Employees.Any()) - { - foreach (var employee in manager.Employees) - { - Console.WriteLine($"\t Employee {employee.Id}, {employee.Name}"); - } - } - else - { - Console.WriteLine($"\t No employees."); - } - } - Console.WriteLine(); + cmd.Undo(); } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Finished sample/Command/Program.cs b/Finished sample/Command/Program.cs index e0cbdd9..6b18a31 100644 --- a/Finished sample/Command/Program.cs +++ b/Finished sample/Command/Program.cs @@ -1,24 +1,31 @@ using Command; -CommandManager commandManager = new (); -IEmployeeManagerRepository repository = new EmployeeManagerRepository(); +Console.Title = "Command"; +CommandManager commandManager = new(); +IEmployeeManagerRepository repository = new EmployeeManagerRepository(); -commandManager.Invoke(new AddEmployeeToManagerList(repository, 1, new Employee(111, "Kevin"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 1, new Employee(111, "Kevin"))); repository.WriteDataStore(); commandManager.Undo(); repository.WriteDataStore(); -commandManager.Invoke(new AddEmployeeToManagerList(repository, 1, new Employee(222, "Clara"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 1, new Employee(222, "Clara"))); repository.WriteDataStore(); -commandManager.Invoke(new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); repository.WriteDataStore(); // try adding the same employee again -commandManager.Invoke(new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); repository.WriteDataStore(); commandManager.UndoAll(); -repository.WriteDataStore(); \ No newline at end of file +repository.WriteDataStore(); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Composite/Implementation.cs b/Finished sample/Composite/Implementation.cs index 67885b3..ec60052 100644 --- a/Finished sample/Composite/Implementation.cs +++ b/Finished sample/Composite/Implementation.cs @@ -1,77 +1,49 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Composite; -namespace Composite +/// +/// Component +/// +public abstract class FileSystemItem { - /// - /// Component - /// - public abstract class FileSystemItem - { - public string Name { get; set; } - - public abstract long GetSize(); + public string Name { get; set; } - public FileSystemItem(string name) - { - Name = name; - } - } + public abstract long GetSize(); + protected FileSystemItem(string name) => Name = name; +} - /// - /// Leaf - /// - public class File : FileSystemItem - { - private long _size; - public File(string name, long size) : base(name) - { - _size = size; - } +/// +/// Leaf +/// +public class File : FileSystemItem +{ + readonly long _size; + public File(string name, long size) : base(name) => _size = size; - public override long GetSize() - { - return _size; - } - } + public override long GetSize() => _size; +} - /// - /// Composite - /// - public class Directory : FileSystemItem - { - private long _size; - private List _fileSystemItems { get; set; } = new List(); - - public Directory(string name, long size) : base(name) - { - _size = size; - } +/// +/// Composite +/// +public class Directory : FileSystemItem +{ + readonly List _fileSystemItems = new(); - public void Add(FileSystemItem itemToAdd) - { - _fileSystemItems.Add(itemToAdd); - } + readonly long _size; + public Directory(string name, long size) : base(name) => _size = size; - public void Remove(FileSystemItem itemToRemove) - { - _fileSystemItems.Remove(itemToRemove); - } + public void Add(FileSystemItem itemToAdd) => _fileSystemItems.Add(itemToAdd); + + public void Remove(FileSystemItem itemToRemove) => _fileSystemItems.Remove(itemToRemove); - public override long GetSize() + public override long GetSize() + { + var treeSize = _size; + foreach (FileSystemItem fileSystemItem in _fileSystemItems) { - var treeSize = _size; - foreach (var fileSystemItem in _fileSystemItems) - { - treeSize += fileSystemItem.GetSize(); - } - return treeSize; + treeSize += fileSystemItem.GetSize(); } + return treeSize; } - - } diff --git a/Finished sample/Composite/Program.cs b/Finished sample/Composite/Program.cs index 810f95f..722327f 100644 --- a/Finished sample/Composite/Program.cs +++ b/Finished sample/Composite/Program.cs @@ -1,4 +1,6 @@ -var root = new Composite.Directory("root", 0); +Console.Title = "Composite"; + +var root = new Composite.Directory("root", 0); var topLevelFile = new Composite.File("toplevel.txt", 100); var topLevelDirectory1 = new Composite.Directory("topleveldirectory1", 4); var topLevelDirectory2 = new Composite.Directory("topleveldirectory2", 4); @@ -17,4 +19,4 @@ Console.WriteLine($"Size of topLevelDirectory2: {topLevelDirectory2.GetSize()}"); Console.WriteLine($"Size of root: {root.GetSize()}"); -Console.ReadKey(); \ No newline at end of file +Console.ReadKey(); diff --git a/Finished sample/Decorator/Implementation.cs b/Finished sample/Decorator/Implementation.cs index 82a2640..c28c6d3 100644 --- a/Finished sample/Decorator/Implementation.cs +++ b/Finished sample/Decorator/Implementation.cs @@ -1,104 +1,91 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Decorator; -namespace Decorator +/// +/// Component (as interface) +/// +public interface IMailService { - /// - /// ConcreteComponent1 - /// - public class CloudMailService : IMailService - { - public bool SendMail(string message) - { - Console.WriteLine($"Message \"{message}\" sent via {nameof(CloudMailService)}."); - return true; - } - } + bool SendMail(string message); +} - /// - /// ConcreteComponent2 - /// - public class OnPremiseMailService : IMailService +/// +/// ConcreteComponent1 +/// +public class CloudMailService : IMailService +{ + public bool SendMail(string message) { - public bool SendMail(string message) - { - Console.WriteLine($"Message \"{message}\" sent via {nameof(OnPremiseMailService)}."); - return true; - } + Console.WriteLine($"Message \"{message}\" " + + $"sent via {nameof(CloudMailService)}."); + return true; } +} - /// - /// Component (as interface) - /// - public interface IMailService +/// +/// ConcreteComponent2 +/// +public class OnPremiseMailService : IMailService +{ + public bool SendMail(string message) { - bool SendMail(string message); + Console.WriteLine($"Message \"{message}\" " + + $"sent via {nameof(OnPremiseMailService)}."); + return true; } +} +/// +/// Decorator +/// +public abstract class MailServiceDecoratorBase : IMailService +{ + readonly IMailService _mailService; + protected MailServiceDecoratorBase(IMailService mailService) => _mailService = mailService; - /// - /// Decorator (as abstract base class) - /// - public abstract class MailServiceDecoratorBase : IMailService - { - private readonly IMailService _mailService; - public MailServiceDecoratorBase(IMailService mailService) - { - _mailService = mailService; - } + public virtual bool SendMail(string message) => _mailService.SendMail(message); +} - public virtual bool SendMail(string message) - { - return _mailService.SendMail(message); - } +/// +/// ConcreteDecorator1 +/// +public class StatisticsDecorator : MailServiceDecoratorBase +{ + public StatisticsDecorator(IMailService mailService) + : base(mailService) + { } - /// - /// ConcreteDecorator1 - /// - public class StatisticsDecorator : MailServiceDecoratorBase + public override bool SendMail(string message) { - public StatisticsDecorator(IMailService mailService) - : base(mailService) - { - } - - public override bool SendMail(string message) - { - // Fake collecting statistics - Console.WriteLine($"Collecting statistics in {nameof(StatisticsDecorator)}."); - return base.SendMail(message); - } + // Fake collecting statistics + Console.WriteLine($"Collecting statistics in {nameof(StatisticsDecorator)}."); + return base.SendMail(message); } +} +/// +/// ConcreteDecorator2 +/// +public class MessageDatabaseDecorator : MailServiceDecoratorBase +{ /// - /// ConcreteDecorator2 + /// A list of sent messages - a "fake" database /// - public class MessageDatabaseDecorator : MailServiceDecoratorBase - { - /// - /// A list of sent messages - a "fake" database - /// - public List SentMessages { get; private set; } = new List(); + public List SentMessages { get; } = new List(); - public MessageDatabaseDecorator(IMailService mailService) - : base(mailService) - { - } + public MessageDatabaseDecorator(IMailService mailService) + : base(mailService) + { } - public override bool SendMail(string message) + public override bool SendMail(string message) + { + if (base.SendMail(message)) { - if (base.SendMail(message)) - { - // store sent message - SentMessages.Add(message); - return true; - }; - - return false; + // store sent message + SentMessages.Add(message); + return true; } + + return false; } } diff --git a/Finished sample/Decorator/Program.cs b/Finished sample/Decorator/Program.cs index 230cbb1..a76a3b5 100644 --- a/Finished sample/Decorator/Program.cs +++ b/Finished sample/Decorator/Program.cs @@ -1,6 +1,8 @@ -// instantiate mail services -using Decorator; +using Decorator; +Console.Title = "Decorator"; + +// instantiate mail services var cloudMailService = new CloudMailService(); cloudMailService.SendMail("Hi there."); diff --git a/Finished sample/DesignPatterns.sln b/Finished sample/DesignPatterns.sln index d3ca260..fa609cf 100644 --- a/Finished sample/DesignPatterns.sln +++ b/Finished sample/DesignPatterns.sln @@ -101,6 +101,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "23 - Interpreter", "23 - In EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interpreter", "Interpreter\Interpreter.csproj", "{39C0A16A-B9F1-444B-9D5D-F46BBB84F746}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{61D1DF2B-393E-4AC1-AE68-0842FD3B1859}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + ReadMe.txt = ReadMe.txt + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Finished sample/Facade/Implementation.cs b/Finished sample/Facade/Implementation.cs index f5a0bcd..9d94170 100644 --- a/Finished sample/Facade/Implementation.cs +++ b/Finished sample/Facade/Implementation.cs @@ -1,75 +1,51 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Facade; -namespace Facade +/// +/// Subsystem class +/// +public class OrderService { - /// - /// Facade - /// - public class DiscountFacade - { - private readonly OrderService _orderService = new (); - private readonly CustomerDiscountBaseService _customerDiscountBaseService = new (); - private readonly DayOfTheWeekFactorService _dayOfTheWeekFactorService = new (); - - public double CalculateDiscountPercentage(int customerId) - { - if (!_orderService.HasEnoughOrders(customerId)) - { - return 0; - } + public static bool HasEnoughOrders(int customerId) => + // does the customer have enough orders? + // fake calculation for demo purposes + customerId > 5; +} - return _customerDiscountBaseService.CalculateDiscountBase(customerId) - * _dayOfTheWeekFactorService.CalculateDayOfTheWeekFactor(); - } - } - - /// - /// Subsystem class - /// - public class OrderService - { - public bool HasEnoughOrders(int customerId) - { - // does the customer have enough orders? - // fake calculation for demo purposes - return (customerId > 5); - } - } +/// +/// Subsystem class +/// +public class CustomerDiscountBaseService +{ + public double CalculateDiscountBase(int customerId) => + // fake calculation for demo purposes + (customerId > 8) ? 10 : 20; +} - /// - /// Subsystem class - /// - public class CustomerDiscountBaseService - { - public double CalculateDiscountBase(int customerId) +/// +/// Subsystem class +/// +public static class DayOfTheWeekFactorService +{ + public static double CalculateDayOfTheWeekFactor() => + // fake calculation for demo purposes + DateTime.UtcNow.DayOfWeek switch { - // fake calculation for demo purposes - return (customerId > 8) ? 10 : 20; - } - } - + DayOfWeek.Saturday or DayOfWeek.Sunday => 0.8, + _ => 1.2, + }; +} - /// - /// Subsystem class - /// - public class DayOfTheWeekFactorService - { - public double CalculateDayOfTheWeekFactor() - { - // fake calculation for demo purposes - switch (DateTime.UtcNow.DayOfWeek) - { - case DayOfWeek.Saturday: - case DayOfWeek.Sunday: - return 0.8; - default: - return 1.2; - } - } - } +/// +/// Facade +/// +public class DiscountFacade +{ + //readonly OrderService _orderService = new(); + readonly CustomerDiscountBaseService _customerDiscountBaseService = new(); + //readonly DayOfTheWeekFactorService _dayOfTheWeekFactorService = new(); + public double CalculateDiscountPercentage(int customerId) => OrderService.HasEnoughOrders(customerId) + ? _customerDiscountBaseService.CalculateDiscountBase(customerId) + * DayOfTheWeekFactorService.CalculateDayOfTheWeekFactor() + : 0; } diff --git a/Finished sample/Facade/Program.cs b/Finished sample/Facade/Program.cs index fac6d6f..63d1eca 100644 --- a/Finished sample/Facade/Program.cs +++ b/Finished sample/Facade/Program.cs @@ -1,7 +1,11 @@ using Facade; - + +Console.Title = "Facade"; + var facade = new DiscountFacade(); -Console.WriteLine($"Discount percentage for customer with id 1: {facade.CalculateDiscountPercentage(1)}"); -Console.WriteLine($"Discount percentage for customer with id 10: {facade.CalculateDiscountPercentage(10)}"); +Console.WriteLine("Discount percentage for customer with id 1: " + + $"{facade.CalculateDiscountPercentage(1)}"); +Console.WriteLine("Discount percentage for customer with id 10: " + + $"{facade.CalculateDiscountPercentage(10)}"); Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/FactoryMethod/Implementation.cs b/Finished sample/FactoryMethod/Implementation.cs index 9c28244..5bbec8b 100644 --- a/Finished sample/FactoryMethod/Implementation.cs +++ b/Finished sample/FactoryMethod/Implementation.cs @@ -1,109 +1,69 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace FactoryMethod; -namespace FactoryMethod +/// +/// Product +/// +public abstract class DiscountService { - /// - /// Product - /// - public abstract class DiscountService - { - public abstract int DiscountPercentage { get; } - - public override string ToString() => GetType().Name; - } - - /// - /// ConcreteProduct - /// - public class CountryDiscountService : DiscountService - { - private readonly string _countryIdentifier; + public abstract int DiscountPercentage { get; } + public override string ToString() => GetType().Name; +} - public CountryDiscountService(string countryIdentifier) - { - _countryIdentifier = countryIdentifier; - } +/// +/// ConcreteProduct +/// +public class CountryDiscountService : DiscountService +{ + readonly string _countryIdentifier; - public override int DiscountPercentage - { - get - { - switch (_countryIdentifier) - { - // if you're from Belgium, you get a better discount :) - case "BE": - return 20; - default: - return 10; - } - } - } - } + public CountryDiscountService(string countryIdentifier) => _countryIdentifier = countryIdentifier; - /// - /// ConcreteProduct - /// - public class CodeDiscountService : DiscountService + public override int DiscountPercentage => _countryIdentifier switch { - private readonly Guid _code; + // if you're from Belgium, you get a better discount :) + "BE" => 20, + _ => 10, + }; +} - public CodeDiscountService(Guid code) - { - _code = code; - } +/// +/// ConcreteProduct +/// +public class CodeDiscountService : DiscountService +{ + readonly Guid _code; - public override int DiscountPercentage - { - // each code returns the same fixed percentage, but a code is only - // valid once - include a check to so whether the code's been used before - // ... - get => 15; - } - } + public CodeDiscountService(Guid code) => _code = code; - /// - /// Creator - /// - public abstract class DiscountFactory - { - public abstract DiscountService CreateDiscountService(); - } + public override int DiscountPercentage => 15; +} - /// - /// ConcretCreator - /// - public class CountryDiscountFactory : DiscountFactory - { - private readonly string _countryIdentifier; - public CountryDiscountFactory(string countryIdentifier) - { - _countryIdentifier = countryIdentifier; - } +/// +/// Creator +/// +public abstract class DiscountFactory +{ + public abstract DiscountService CreateDiscountService(); +} - public override DiscountService CreateDiscountService() - { - return new CountryDiscountService(_countryIdentifier); - } - } +/// +/// ConcreteCreator +/// +public class CountryDiscountFactory : DiscountFactory +{ + readonly string _countryIdentifier; + public CountryDiscountFactory(string countryIdentifier) => _countryIdentifier = countryIdentifier; - /// - /// ConcreteCreator - /// - public class CodeDiscountFactory : DiscountFactory - { - private readonly Guid _code; + public override DiscountService CreateDiscountService() => new CountryDiscountService(_countryIdentifier); +} + +/// +/// ConcreteCreator +/// +public class CodeDiscountFactory : DiscountFactory +{ + readonly Guid _code; - public CodeDiscountFactory(Guid code) - { - _code = code; - } - public override DiscountService CreateDiscountService() - { - return new CodeDiscountService(_code); - } - } + public CodeDiscountFactory(Guid code) => _code = code; + public override DiscountService CreateDiscountService() => new CodeDiscountService(_code); } diff --git a/Finished sample/FactoryMethod/Program.cs b/Finished sample/FactoryMethod/Program.cs index c3c42e1..73a7ce6 100644 --- a/Finished sample/FactoryMethod/Program.cs +++ b/Finished sample/FactoryMethod/Program.cs @@ -1,13 +1,16 @@ using FactoryMethod; - + +Console.Title = "Factory Method"; + var factories = new List { - new CodeDiscountFactory(Guid.NewGuid()), + new CodeDiscountFactory(Guid.NewGuid()), new CountryDiscountFactory("BE") }; -foreach (var factory in factories) +foreach (DiscountFactory factory in factories) { - var discountService = factory.CreateDiscountService(); - Console.WriteLine($"Percentage {discountService.DiscountPercentage} coming from {discountService}"); -} + DiscountService discountService = factory.CreateDiscountService(); + Console.WriteLine($"Percentage {discountService.DiscountPercentage} " + + $"coming from {discountService}"); +} Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Flyweight/Implementation.cs b/Finished sample/Flyweight/Implementation.cs index 84c64ed..dddbfb1 100644 --- a/Finished sample/Flyweight/Implementation.cs +++ b/Finished sample/Flyweight/Implementation.cs @@ -1,113 +1,103 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Flyweight; -namespace Flyweight +/// +/// Flyweight +/// +public interface ICharacter { - /// - /// Flyweight - /// - public interface ICharacter + void Draw(string fontFamily, int fontSize); +} + +/// +/// Concrete Flyweight +/// +public class CharacterA : ICharacter +{ + readonly char _actualCharacter = 'a'; + string _fontFamily = string.Empty; + int _fontSize; + + public void Draw(string fontFamily, int fontSize) { - void Draw(string fontFamily, int fontSize); + _fontFamily = fontFamily; + _fontSize = fontSize; + Console.WriteLine($"Drawing {_actualCharacter}, {_fontFamily} {_fontSize}"); } +} - /// - /// Concrete Flyweight - /// - public class CharacterA : ICharacter - { - private char _actualCharacter = 'a'; - private string _fontFamily = string.Empty; - private int _fontSize; +/// +/// Concrete Flyweight +/// +public class CharacterB : ICharacter +{ + readonly char _actualCharacter = 'b'; + string _fontFamily = string.Empty; + int _fontSize; - public void Draw(string fontFamily, int fontSize) - { - _fontFamily = fontFamily; - _fontSize = fontSize; - Console.WriteLine($"Drawing {_actualCharacter}, {_fontFamily} {_fontSize}"); - } + public void Draw(string fontFamily, int fontSize) + { + _fontFamily = fontFamily; + _fontSize = fontSize; + Console.WriteLine($"Drawing {_actualCharacter}, {_fontFamily} {_fontSize}"); } +} - /// - /// Concrete Flyweight - /// - public class CharacterB : ICharacter - { - private char _actualCharacter = 'b'; - private string _fontFamily = string.Empty; - private int _fontSize; +/// +/// FlyweightFactory +/// +public class CharacterFactory +{ + readonly Dictionary _characters = new(); - public void Draw(string fontFamily, int fontSize) + public ICharacter? GetCharacter(char characterIdentifier) + { + // Does the character dictionary contain the one we need? + if (_characters.ContainsKey(characterIdentifier)) { - _fontFamily = fontFamily; - _fontSize = fontSize; - Console.WriteLine($"Drawing {_actualCharacter}, {_fontFamily} {_fontSize}"); + Console.WriteLine("Character reuse"); + return _characters[characterIdentifier]; } - } - - /// - /// FlyweightFactory - /// - public class CharacterFactory - { - private readonly Dictionary _characters = new (); - public ICharacter? GetCharacter(char characterIdentifier) - { - // Coes the character dictionary contain the one we need? - if (_characters.ContainsKey(characterIdentifier)) - { - Console.WriteLine("Character reuse"); + // The character isn't in the dictionary. + // Create it, store it, return it. + Console.WriteLine("Character construction"); + switch (characterIdentifier) + { + case 'a': + _characters[characterIdentifier] = new CharacterA(); + return _characters[characterIdentifier]; + case 'b': + _characters[characterIdentifier] = new CharacterB(); return _characters[characterIdentifier]; - } - - // The character isn't in the dictionary. - // Create it, store it, return it. - Console.WriteLine("Character construction"); - switch (characterIdentifier) - { - case 'a': - _characters[characterIdentifier] = new CharacterA(); - return _characters[characterIdentifier]; - case 'b': - _characters[characterIdentifier] = new CharacterB(); - return _characters[characterIdentifier]; // and so on... - } - - return null; } - public ICharacter CreateParagraph(List characters, int location) - { - return new Paragraph(characters, location); - } + return null; } - /// - /// Unshared Concrete Flyweight - /// - public class Paragraph : ICharacter - { - private int _location; - private List _characters = new(); + public static ICharacter CreateParagraph(List characters, int location) => new Paragraph(characters, location); +} - public Paragraph(List characters, int location) - { - _characters = characters; - _location = location; - } +/// +/// Unshared Concrete Flyweight +/// +public class Paragraph : ICharacter +{ + readonly int _location; + readonly List _characters = new(); - public void Draw(string fontFamily, int fontSize) + public Paragraph(List characters, int location) + { + _characters = characters; + _location = location; + } + + public void Draw(string fontFamily, int fontSize) + { + Console.WriteLine($"Drawing in paragraph at location {_location}"); + foreach (ICharacter character in _characters) { - Console.WriteLine($"Drawing in paragraph at location {_location}"); - foreach (var character in _characters) - { - character.Draw(fontFamily, fontSize); - } + character.Draw(fontFamily, fontSize); } } } diff --git a/Finished sample/Flyweight/Program.cs b/Finished sample/Flyweight/Program.cs index bacf227..4a3a04d 100644 --- a/Finished sample/Flyweight/Program.cs +++ b/Finished sample/Flyweight/Program.cs @@ -1,11 +1,13 @@ using Flyweight; -var aBunchOfCharacters = "abba"; +Console.Title = "Flyweight"; + +var aBunchOfCharacters = "abba"; var characterFactory = new CharacterFactory(); // Get the flyweight(s) -var characterObject = characterFactory.GetCharacter(aBunchOfCharacters[0]); +ICharacter? characterObject = characterFactory.GetCharacter(aBunchOfCharacters[0]); // Pass through extrinsic state characterObject?.Draw("Arial", 12); @@ -19,8 +21,11 @@ characterObject?.Draw("Comic Sans", 18); // create unshared concrete flyweight (paragraph) -var paragraph = characterFactory.CreateParagraph( - new List() { characterObject }, 1); +ICharacter paragraph = CharacterFactory.CreateParagraph( + characterObject is null + ? new List(0) + : new List() { characterObject } + , 1); // draw the paragraph paragraph.Draw("Lucinda", 12); diff --git a/Finished sample/Interpreter/Implementation.cs b/Finished sample/Interpreter/Implementation.cs index acf64d6..701a328 100644 --- a/Finished sample/Interpreter/Implementation.cs +++ b/Finished sample/Interpreter/Implementation.cs @@ -1,176 +1,166 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Interpreter; -namespace Interpreter +/// +/// Context +/// +public class RomanContext { - /// - /// Context - /// - public class RomanContext + public int Input { get; set; } + public string Output { get; set; } = string.Empty; + public RomanContext(int input) => Input = input; +} + +/// +/// AbstractExpression +/// +public abstract class RomanExpression +{ + public abstract void Interpret(RomanContext value); +} + +// 9 = IX +// 8 = VIII +// 7 = VII +// 6 = VI +// 5 = V +// 4 = IV +// 3 = III +// 2 = II +// 1 = I + +// simplified - each combination is reachable with subtraction and these 4: +// 9 = IX +// 5 = V +// 4 = IV +// 1 = I + +/// +/// TerminalExpression +/// +public class RomanOneExpression : RomanExpression +{ + public override void Interpret(RomanContext value) { - public int Input { get; set; } - public string Output { get; set; } = string.Empty; - public RomanContext(int input) + while (value.Input - 9 >= 0) { - Input = input; + value.Output += "IX"; + value.Input -= 9; } - } - /// - /// AbstractExpression - /// - public abstract class RomanExpression - { - public abstract void Interpret(RomanContext value); - } + while (value.Input - 5 >= 0) + { + value.Output += "V"; + value.Input -= 5; + } - // 9 = IX - // 8 = VIII - // 7 = VII - // 6 = VI - // 5 = V - // 4 = IV - // 3 = III - // 2 = II - // 1 = I - - // simplified - each combination is reachable with substraction and these 4: - // 9 = IX - // 5 = V - // 4 = IV - // 1 = I - - /// - /// TerminalExpression - /// - public class RomanOneExpression : RomanExpression - { - public override void Interpret(RomanContext value) + while (value.Input - 4 >= 0) + { + value.Output += "IV"; + value.Input -= 4; + } + + while (value.Input - 1 >= 0) { - while ((value.Input - 9) >= 0) - { - value.Output += "IX"; - value.Input -= 9; - } - - while ((value.Input - 5) >= 0) - { - value.Output += "V"; - value.Input -= 5; - } - - while ((value.Input - 4) >= 0) - { - value.Output += "IV"; - value.Input -= 4; - } - - while ((value.Input - 1) >= 0) - { - value.Output += "I"; - value.Input -= 1; - } + value.Output += "I"; + value.Input--; } } +} - // 90 = XC - // 80 = LIII - // 70 = LII - // 60 = LX - // 50 = L - // 40 = XL - // 30 = XXX - // 20 = XX - // 10 = X - - // simplified - each combination is reachable with substraction and these 4: - // 90 = XC - // 50 = L - // 40 = XL - // 10 = X - - /// - /// TerminalExpression - /// - public class RomanTenExpression : RomanExpression +// 90 = XC +// 80 = LIII +// 70 = LII +// 60 = LX +// 50 = L +// 40 = XL +// 30 = XXX +// 20 = XX +// 10 = X + +// simplified - each combination is reachable with substraction and these 4: +// 90 = XC +// 50 = L +// 40 = XL +// 10 = X + +/// +/// TerminalExpression +/// +public class RomanTenExpression : RomanExpression +{ + public override void Interpret(RomanContext value) { - public override void Interpret(RomanContext value) + while (value.Input - 90 >= 0) { - while ((value.Input - 90) >= 0) - { - value.Output += "XC"; - value.Input -= 90; - } - - while ((value.Input - 50) >= 0) - { - value.Output += "L"; - value.Input -= 50; - } - - while ((value.Input - 40) >= 0) - { - value.Output += "XL"; - value.Input -= 40; - } - - while ((value.Input - 10) >= 0) - { - value.Output += "X"; - value.Input -= 10; - } + value.Output += "XC"; + value.Input -= 90; + } + + while (value.Input - 50 >= 0) + { + value.Output += "L"; + value.Input -= 50; + } + + while (value.Input - 40 >= 0) + { + value.Output += "XL"; + value.Input -= 40; + } + + while (value.Input - 10 >= 0) + { + value.Output += "X"; + value.Input -= 10; } } +} - // 900 = CM - // 800 = DCCC - // 700 = DCC - // 600 = DC - // 500 = D - // 400 = CD - // 300 = CCC - // 200 = CC - // 100 = C - - // simplified - each combination is reachable with substraction and these 4: - // 900 = CM - // 500 = D - // 400 = CD - // 100 = C - - /// - /// TerminalExpression - /// - public class RomanHunderdExpression : RomanExpression +// 900 = CM +// 800 = DCCC +// 700 = DCC +// 600 = DC +// 500 = D +// 400 = CD +// 300 = CCC +// 200 = CC +// 100 = C + +// simplified - each combination is reachable with substraction and these 4: +// 900 = CM +// 500 = D +// 400 = CD +// 100 = C + +/// +/// TerminalExpression +/// +public class RomanHunderdExpression : RomanExpression +{ + public override void Interpret(RomanContext value) { - public override void Interpret(RomanContext value) + while (value.Input - 900 >= 0) + { + value.Output += "CM"; + value.Input -= 900; + } + + while (value.Input - 500 >= 0) + { + value.Output += "D"; + value.Input -= 500; + } + + while (value.Input - 400 >= 0) + { + value.Output += "CD"; + value.Input -= 400; + } + + while (value.Input - 100 >= 0) { - while ((value.Input - 900) >= 0) - { - value.Output += "CM"; - value.Input -= 900; - } - - while ((value.Input - 500) >= 0) - { - value.Output += "D"; - value.Input -= 500; - } - - while ((value.Input - 400) >= 0) - { - value.Output += "CD"; - value.Input -= 400; - } - - while ((value.Input - 100) >= 0) - { - value.Output += "C"; - value.Input -= 100; - } + value.Output += "C"; + value.Input -= 100; } } } diff --git a/Finished sample/Interpreter/Program.cs b/Finished sample/Interpreter/Program.cs index db45324..57dfbc1 100644 --- a/Finished sample/Interpreter/Program.cs +++ b/Finished sample/Interpreter/Program.cs @@ -1,5 +1,7 @@ using Interpreter; +Console.Title = "Interpreter"; + var expressions = new List { new RomanHunderdExpression(), @@ -8,22 +10,24 @@ }; var context = new RomanContext(5); -foreach (var expression in expressions) +foreach (RomanExpression expression in expressions) { expression.Interpret(context); } Console.WriteLine($"Translating Arabic numerals to Roman numerals: 5 = {context.Output}"); context = new RomanContext(81); -foreach (var expression in expressions) +foreach (RomanExpression expression in expressions) { expression.Interpret(context); } Console.WriteLine($"Translating Arabic numerals to Roman numerals: 81 = {context.Output}"); context = new RomanContext(733); -foreach (var expression in expressions) +foreach (RomanExpression expression in expressions) { expression.Interpret(context); } Console.WriteLine($"Translating Arabic numerals to Roman numerals: 733 = {context.Output}"); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Iterator/Implementation.cs b/Finished sample/Iterator/Implementation.cs index 4146ec0..ec78222 100644 --- a/Finished sample/Iterator/Implementation.cs +++ b/Finished sample/Iterator/Implementation.cs @@ -1,90 +1,74 @@ -namespace Iterator +namespace Iterator; + +public class Person { - public class Person - { - public string Name { get; set; } - public string Country { get; set; } + public string Name { get; set; } + public string Country { get; set; } - public Person(string name, string country) - { - Name = name; - Country = country; - } - } - - /// - /// Iterator - /// - public interface IPeopleIterator + public Person(string name, string country) { - Person First(); - Person Next(); - bool IsDone { get; } - Person CurrentItem { get; } + Name = name; + Country = country; } +} - /// - /// ConcreteIterator - /// - public class PeopleIterator : IPeopleIterator - { - private PeopleCollection _peopleCollection; - private int _current = 0; - - public PeopleIterator(PeopleCollection collection) - { - _peopleCollection = collection; - } +/// +/// Iterator +/// +public interface IPeopleIterator +{ + Person? First(); + Person? Next(); + bool IsDone { get; } + Person? CurrentItem { get; } +} - public Person First() - { - _current = 0; - return _peopleCollection - .OrderBy(p => p.Name).ToList()[_current]; - } +/// +/// Aggregate +/// +public interface IPeopleCollection +{ + IPeopleIterator CreateIterator(); +} - public Person Next() - { - _current++; - if (!IsDone) - { - return _peopleCollection - .OrderBy(p => p.Name).ToList()[_current]; - } - else - { - return null; - } - } +/// +/// ConcreteAggregate +/// +public class PeopleCollection : List, IPeopleCollection +{ + public IPeopleIterator CreateIterator() => new PeopleIterator(this); +} - public bool IsDone - { - get { return _current >= _peopleCollection.Count; } - } +/// +/// ConcreteIterator +/// +public class PeopleIterator : IPeopleIterator +{ + readonly PeopleCollection _peopleCollection; + int _current = 0; - public Person CurrentItem - { - get { return _peopleCollection - .OrderBy(p => p.Name).ToList()[_current]; } - } - } + public PeopleIterator(PeopleCollection collection) => _peopleCollection = collection; - /// - /// Aggregate - /// - public interface IPeopleCollection + public bool IsDone => _current >= _peopleCollection.Count; + + public Person CurrentItem => _peopleCollection + .OrderBy(p => p.Name).ToList()[_current]; + + public Person? First() { - IPeopleIterator CreateIterator(); + _current = 0; + return IsDone + ? null + : _peopleCollection + .OrderBy(p => p.Name).ToList()[_current]; } - /// - /// ConcreteAggregate - /// - public class PeopleCollection : List, IPeopleCollection + public Person? Next() { - public IPeopleIterator CreateIterator() - { - return new PeopleIterator(this); - } + _current++; + return IsDone + ? null + : _peopleCollection + .OrderBy(p => p.Name).ToList()[_current]; } } diff --git a/Finished sample/Iterator/Program.cs b/Finished sample/Iterator/Program.cs index f59562f..b65b6ba 100644 --- a/Finished sample/Iterator/Program.cs +++ b/Finished sample/Iterator/Program.cs @@ -1,21 +1,26 @@ using Iterator; +Console.Title = "Iterator"; + // create the collection -PeopleCollection people = new PeopleCollection(); -people.Add(new Person("Kevin Dockx", "Belgium")); -people.Add(new Person("Gill Cleeren", "Belgium")); -people.Add(new Person("Roland Guijt", "The Netherlands")); -people.Add(new Person("Thomas Claudius Huber", "Germany")); +PeopleCollection people = new() +{ + new Person("Kevin Dockx", "Belgium"), + new Person("Gill Cleeren", "Belgium"), + new Person("Roland Guijt", "The Netherlands"), + new Person("Thomas Claudius Huber", "Germany") +}; -// create the interator -var peopleIterator = people.CreateIterator(); +// create the iterator +IPeopleIterator peopleIterator = people.CreateIterator(); // use the iterator to run through the people // in the collection; they should come out // in alphabetical order -for (Person person = peopleIterator.First(); - !peopleIterator.IsDone; - person = peopleIterator.Next()) +Person person = peopleIterator.First()!; +while (!peopleIterator.IsDone) { - Console.WriteLine(person?.Name); + Console.WriteLine(person.Name); + person = peopleIterator.Next()!; } +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Mediator/Implementation.cs b/Finished sample/Mediator/Implementation.cs index 05fbc91..175b62a 100644 --- a/Finished sample/Mediator/Implementation.cs +++ b/Finished sample/Mediator/Implementation.cs @@ -1,135 +1,108 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Mediator; + +//public abstract class ChatRoom +//{ +// public abstract void Register(TeamMember teamMember); +// public abstract void Send(string from, string message); +//} + +/// +/// Mediator +/// +public interface IChatRoom +{ + void Register(TeamMember teamMember); + void Send(string from, string message); + void Send(string from, string to, string message); + void SendTo(string from, string message) where T : TeamMember; +} -namespace Mediator +/// +/// Colleague +/// +public abstract class TeamMember { - /// - /// Mediator - /// - public interface IChatRoom - { - void Register(TeamMember teamMember); - void Send(string from, string message); - void Send(string from, string to, string message); - void SendTo(string from, string message) where T : TeamMember; - } + IChatRoom? _chatroom; + public string Name { get; set; } + protected TeamMember(string name) => Name = name; - /// - /// Colleague - /// - public abstract class TeamMember - { - public string Name { get; set; } + internal void SetChatroom(IChatRoom chatRoom) => _chatroom = chatRoom; + public void Send(string to, string message) => _chatroom?.Send(Name, to, message); - private IChatRoom? _chatroom; + public void SendTo(string message) where T : TeamMember => _chatroom?.SendTo(Name, message); - public TeamMember(string name) - { - Name = name; - } - - internal void SetChatroom(IChatRoom chatRoom) - { - _chatroom = chatRoom; - } - - public void Send(string message) - { - _chatroom?.Send(Name, message); - } + public void Send(string message) => _chatroom?.Send(Name, message); - public void Send(string to, string message) - { - _chatroom?.Send(Name, to, message); - } - - public void SendTo(string message) where T : TeamMember - { - _chatroom?.SendTo(Name, message); - } + public virtual void Receive(string from, string message) => Console.WriteLine($"Message {from} to {Name}: {message}"); +} - public virtual void Receive(string from, string message) - { - Console.WriteLine($"message from {from} to {Name}: {message}"); - } +/// +/// ConcreteColleague +/// +public class Lawyer : TeamMember +{ + public Lawyer(string name) : base(name) + { } - /// - /// ConcreteColleague - /// - public class Lawyer : TeamMember + public override void Receive(string from, string message) { - private List _teamMembersInChat = new(); - - public Lawyer(string name) : base(name) - { - } - - public override void Receive(string from, string message) - { - Console.Write($"{nameof(Lawyer)} {Name} received: "); - base.Receive(from, message); - } + Console.WriteLine($"{nameof(Lawyer)} {Name} received: "); + base.Receive(from, message); } +} - - /// - /// ConcreteColleague - /// - public class AccountManager : TeamMember +/// +/// ConcreteColleague +/// +public class AccountManager : TeamMember +{ + public AccountManager(string name) : base(name) { - public AccountManager(string name) : base(name) - { - } + } - public override void Receive(string from, string message) - { - Console.Write($"{nameof(AccountManager)} {Name} received: "); - base.Receive(from, message); - } + public override void Receive(string from, string message) + { + Console.WriteLine($"{nameof(AccountManager)} {Name} received: "); + base.Receive(from, message); } +} +/// +/// ConcreteMediator +/// +public class TeamChatRoom : IChatRoom +{ + readonly Dictionary teamMembers = new(); - /// - /// ConcreteMediator - /// - public class TeamChatRoom : IChatRoom + public void Register(TeamMember teamMember) { - private readonly Dictionary teamMembers = new(); - - public void Register(TeamMember teamMember) + teamMember.SetChatroom(this); + if (!teamMembers.ContainsKey(teamMember.Name)) { - teamMember.SetChatroom(this); - if (!teamMembers.ContainsKey(teamMember.Name)) - { - teamMembers.Add(teamMember.Name, teamMember); - } + teamMembers.Add(teamMember.Name, teamMember); } + } - public void Send(string from, string message) + public void Send(string from, string message) + { + foreach (TeamMember teamMember in teamMembers.Values) { - foreach (var teamMember in teamMembers.Values) - { - teamMember.Receive(from, message); - } + teamMember.Receive(from, message); } + } - public void Send(string from, string to, string message) - { - var teamMember = teamMembers[to]; - teamMember?.Receive(from, message); - } + public void Send(string from, string to, string message) + { + TeamMember teamMember = teamMembers[to]; + teamMember?.Receive(from, message); + } - public void SendTo(string from, string message) where T : TeamMember + public void SendTo(string from, string message) where T : TeamMember + { + foreach (T teamMember in teamMembers.Values.OfType()) { - foreach (var teamMember in teamMembers.Values.OfType()) - { - teamMember.Receive(from, message); - } + teamMember.Receive(from, message); } } } - \ No newline at end of file diff --git a/Finished sample/Mediator/Program.cs b/Finished sample/Mediator/Program.cs index a528358..a1c3668 100644 --- a/Finished sample/Mediator/Program.cs +++ b/Finished sample/Mediator/Program.cs @@ -1,5 +1,7 @@ using Mediator; +Console.Title = "Mediator"; + TeamChatRoom teamChatroom = new(); var sven = new Lawyer("Sven"); @@ -18,4 +20,6 @@ sven.Send("On it!"); sven.Send("Ann", "Could you join me in a Teams call?"); sven.Send("Ann", "All good :)"); -ann.SendTo("The file was approved!"); \ No newline at end of file +ann.SendTo("The file was approved!"); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Memento/Implementation.cs b/Finished sample/Memento/Implementation.cs index f1a7f2a..34edf57 100644 --- a/Finished sample/Memento/Implementation.cs +++ b/Finished sample/Memento/Implementation.cs @@ -1,229 +1,209 @@ -namespace Memento +namespace Memento; + +public class Employee { - /// - /// ICommand - /// - public interface ICommand - { - void Execute(); - bool CanExecute(); - void Undo(); - } + public int Id { get; set; } + public string Name { get; set; } - /// - /// Memento - /// - public class AddEmployeeToManagerListMemento + public Employee(int id, string name) { - public int ManagerId { get; private set; } - public Employee? Employee { get; private set; } - - public AddEmployeeToManagerListMemento(int managerId, Employee? employee) - { - ManagerId = managerId; - Employee = employee; - } + Id = id; + Name = name; } - - /// - /// ConcreteCommand - /// - public class AddEmployeeToManagerList : ICommand +} +public class Manager : Employee +{ + public List Employees = new(); + public Manager(int id, string name) + : base(id, name) { - private readonly IEmployeeManagerRepository _employeeManagerRepository; - private int _managerId; - private Employee? _employee; - - public AddEmployeeToManagerList( - IEmployeeManagerRepository employeeManagerRepository, - int managerId, - Employee? employee) - { - _employeeManagerRepository = employeeManagerRepository; - _managerId = managerId; - _employee = employee; - } - - public AddEmployeeToManagerListMemento CreateMemento() - { - return new AddEmployeeToManagerListMemento(_managerId, _employee); - } - - public void RestoreMemento(AddEmployeeToManagerListMemento memento) - { - _managerId = memento.ManagerId; - _employee = memento.Employee; - } + } +} - public bool CanExecute() - { - // potentially check against business/technical rules that might block execution +/// +/// Receiver (interface) +/// +public interface IEmployeeManagerRepository +{ + void AddEmployee(int managerId, Employee employee); + void RemoveEmployee(int managerId, Employee employee); + bool HasEmployee(int managerId, int employeeId); + void WriteDataStore(); +} + +/// +/// Receiver (implementation) +/// +public class EmployeeManagerRepository : IEmployeeManagerRepository +{ + // for demo purposes, use an in-memory datastore as a fake "manager list" + readonly List _managers = new() + { new Manager(1, "Katie"), new Manager(2, "Geoff") }; - // employee shouldn't be null - if (_employee == null) - { - return false; - } + public void AddEmployee(int managerId, Employee employee) => + // in real-life, add additional input & error checks + _managers.First(m => m.Id == managerId).Employees.Add(employee); - // employee shouldn't be on the manager's list already - if (_employeeManagerRepository.HasEmployee(_managerId, _employee.Id)) - { - return false; - } + public void RemoveEmployee(int managerId, Employee employee) => + // in real-life, add additional input & error checks + _managers.First(m => m.Id == managerId).Employees.Remove(employee); - // other potential rule(s): ensure that an employee can only be added to - // one manager's list at the same time, etc. - return true; - } + public bool HasEmployee(int managerId, int employeeId) => + // in real-life, add additional input & error checks + _managers.First(m => m.Id == managerId) + .Employees.Any(e => e.Id == employeeId); - public void Execute() + /// + /// For demo purposes, write out the data store to the console window + /// + public void WriteDataStore() + { + foreach (Manager manager in _managers) { - if (_employee == null) + Console.WriteLine($"Manager {manager.Id}, {manager.Name}"); + if (manager.Employees.Any()) { - return; + foreach (Employee employee in manager.Employees) + { + Console.WriteLine($"\t Employee {employee.Id}, {employee.Name}"); + } } - - _employeeManagerRepository.AddEmployee(_managerId, _employee); - } - - public void Undo() - { - if (_employee == null) + else { - return; + Console.WriteLine("\t No employees."); } - - _employeeManagerRepository.RemoveEmployee(_managerId, _employee); } } +} - /// - /// CareTaker (and Invoker from the Command pattern) - /// - public class CommandManager +/// +/// Command +/// +public interface ICommand +{ + void Execute(); + bool CanExecute(); + void Undo(); +} + +/// +/// Memento +/// +public class AddEmployeeToManagerListMemento +{ + public int ManagerId { get; } + public Employee? Employee { get; } + + public AddEmployeeToManagerListMemento(int managerId, Employee? employee) { - private readonly Stack _mementos = new (); - private AddEmployeeToManagerList? _command; + ManagerId = managerId; + Employee = employee; + } +} - public void Invoke(AddEmployeeToManagerList command) - { - // if the command has not been stored yet, store it - we will - // reuse it instead of storing different instances +/// +/// ConcreteCommand & Originator +/// +public class AddEmployeeToManagerList : ICommand +{ + readonly IEmployeeManagerRepository _employeeManagerRepository; + int _managerId; + Employee? _employee; + + public AddEmployeeToManagerList( + IEmployeeManagerRepository employeeManagerRepository, + int managerId, + Employee? employee) + { + _employeeManagerRepository = employeeManagerRepository; + _managerId = managerId; + _employee = employee; + } - if (_command == null) - { - _command = command; - } + public AddEmployeeToManagerListMemento CreateMemento() => new(_managerId, _employee); - if (command.CanExecute()) - { - command.Execute(); - _mementos.Push(command.CreateMemento()); - } - } + public void RestoreMemento(AddEmployeeToManagerListMemento memento) + { + _managerId = memento.ManagerId; + _employee = memento.Employee; + } - public void Undo() + public bool CanExecute() + { + // employee shouldn't be null + if (_employee == null) { - if (_mementos.Any()) - { - _command?.RestoreMemento(_mementos.Pop()); - _command?.Undo(); - } + return false; } - public void UndoAll() + // employee shouldn't be on the manager's list already + if (_employeeManagerRepository.HasEmployee(_managerId, _employee.Id)) { - while (_mementos.Any()) - { - _command?.RestoreMemento(_mementos.Pop()); - _command?.Undo(); - } + return false; } - } - + // other potential rule(s): ensure that an employee can only be added to + // one manager's list at the same time, etc. + return true; + } - public class Employee + public void Execute() { - public int Id { get; set; } - public string Name { get; set; } - - public Employee(int id, string name) + if (_employee == null) { - Id = id; - Name = name; + return; } + _employeeManagerRepository.AddEmployee(_managerId, _employee); } - public class Manager : Employee + public void Undo() { - public List Employees = new(); - public Manager(int id, string name) - : base(id, name) + if (_employee == null) { + return; } - } - /// - /// Receiver (interface) - /// - public interface IEmployeeManagerRepository - { - void AddEmployee(int managerId, Employee employee); - void RemoveEmployee(int managerId, Employee employee); - bool HasEmployee(int managerId, int employeeId); - void WriteDataStore(); + _employeeManagerRepository.RemoveEmployee(_managerId, _employee); } +} - /// - /// Receiver (implementation) - /// - public class EmployeeManagerRepository : IEmployeeManagerRepository +/// +/// Invoker & Caretaker +/// +public class CommandManager +{ + readonly Stack _mementos = new(); + AddEmployeeToManagerList? _command; + + public void Invoke(ICommand command) { - // for demo purposes, use an in-memory datastore as a fake "manager list" - private List _managers = new List() - { new Manager(1, "Katie"), new Manager(2, "Geoff") }; + // if the command has not been stored yet, store it - we will + // reuse it instead of storing different instances - public void AddEmployee(int managerId, Employee employee) - { - // in real-life, add additional input & error checks - _managers.First(m => m.Id == managerId).Employees.Add(employee); - } + _command ??= (AddEmployeeToManagerList)command; - public void RemoveEmployee(int managerId, Employee employee) + if (command.CanExecute()) { - // in real-life, add additional input & error checks - _managers.First(m => m.Id == managerId).Employees.Remove(employee); + command.Execute(); + _mementos.Push(((AddEmployeeToManagerList)command).CreateMemento()); } + } - public bool HasEmployee(int managerId, int employeeId) + public void Undo() + { + if (_mementos.Any()) { - // in real-life, add additional input & error checks - return _managers.First(m => m.Id == managerId).Employees.Any(e => e.Id == employeeId); + _command?.RestoreMemento(_mementos.Pop()); + _command?.Undo(); } + } - - /// - /// For demo purposes, write out the data store to the console window - /// - public void WriteDataStore() + public void UndoAll() + { + while (_mementos.Any()) { - foreach (var manager in _managers) - { - Console.WriteLine($"Manager {manager.Id}, {manager.Name}"); - if (manager.Employees.Any()) - { - foreach (var employee in manager.Employees) - { - Console.WriteLine($"\t Employee {employee.Id}, {employee.Name}"); - } - } - else - { - Console.WriteLine($"\t No employees."); - } - } - Console.WriteLine(); + _command?.RestoreMemento(_mementos.Pop()); + _command?.Undo(); } } } \ No newline at end of file diff --git a/Finished sample/Memento/Program.cs b/Finished sample/Memento/Program.cs index 426c06f..50e0b77 100644 --- a/Finished sample/Memento/Program.cs +++ b/Finished sample/Memento/Program.cs @@ -1,24 +1,31 @@ using Memento; +Console.Title = "Memento"; + CommandManager commandManager = new(); IEmployeeManagerRepository repository = new EmployeeManagerRepository(); - -commandManager.Invoke(new AddEmployeeToManagerList(repository, 1, new Employee(111, "Kevin"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 1, new Employee(111, "Kevin"))); repository.WriteDataStore(); commandManager.Undo(); repository.WriteDataStore(); -commandManager.Invoke(new AddEmployeeToManagerList(repository, 1, new Employee(222, "Clara"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 1, new Employee(222, "Clara"))); repository.WriteDataStore(); -commandManager.Invoke(new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); repository.WriteDataStore(); // try adding the same employee again -commandManager.Invoke(new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); +commandManager.Invoke( + new AddEmployeeToManagerList(repository, 2, new Employee(333, "Tom"))); repository.WriteDataStore(); commandManager.UndoAll(); -repository.WriteDataStore(); \ No newline at end of file +repository.WriteDataStore(); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Observer/Implementation.cs b/Finished sample/Observer/Implementation.cs index 148ea3a..592f4dc 100644 --- a/Finished sample/Observer/Implementation.cs +++ b/Finished sample/Observer/Implementation.cs @@ -1,89 +1,79 @@ -namespace Observer -{ - public class TicketChange - { - public int Amount { get; private set; } - public int ArtistId { get; private set; } +namespace Observer; - public TicketChange(int artistId, int amount) - { - ArtistId = artistId; - Amount = amount; - } - } +public class TicketChange +{ + public int Amount { get; } + public int ArtistId { get; } - /// - /// Subject - /// - public abstract class TicketChangeNotifier + public TicketChange(int artistId, int amount) { - private List _observers = new(); + ArtistId = artistId; + Amount = amount; + } +} - public void AddObserver(ITicketChangeListener observer) - { - _observers.Add(observer); - } +/// +/// Subject +/// +public abstract class TicketChangeNotifier +{ + readonly List _observers = new(); - public void RemoveObserver(ITicketChangeListener observer) - { - _observers.Remove(observer); - } + public void AddObserver(ITicketChangeListener observer) => _observers.Add(observer); + public void RemoveObserver(ITicketChangeListener observer) => _observers.Remove(observer); - public void Notify(TicketChange ticketChange) + public void Notify(TicketChange ticketChange) + { + foreach (ITicketChangeListener observer in _observers) { - foreach (var observer in _observers) - { - observer.ReceiveTicketChangeNotification(ticketChange); - } + observer.ReceiveTicketChangeNotification(ticketChange); } } +} - /// - /// ConcreteSubject - /// - public class OrderService : TicketChangeNotifier - { - public void CompleteTicketSale(int artistId, int amount) - { - // change local datastore. Datastore omitted in demo implementation. - Console.WriteLine($"{nameof(OrderService)} is changing its state."); - // notify observers - Console.WriteLine($"{nameof(OrderService)} is notifying observers..."); - Notify(new TicketChange(artistId, amount)); - } - } +/// +/// Observer +/// +public interface ITicketChangeListener +{ + void ReceiveTicketChangeNotification(TicketChange ticketChange); +} - /// - /// Observer - /// - public interface ITicketChangeListener +/// +/// ConcreteSubject +/// +public class OrderService : TicketChangeNotifier +{ + public void CompleteTicketSale(int artistId, int amount) { - void ReceiveTicketChangeNotification(TicketChange ticketChange); + // change local datastore. Datastore omitted in demo implementation. + Console.WriteLine($"{nameof(OrderService)} is changing its state."); + // notify observers + Console.WriteLine($"{nameof(OrderService)} is notifying observers..."); + Notify(new TicketChange(artistId, amount)); } +} - /// - /// ConcreteObserver - /// - public class TicketResellerService : ITicketChangeListener - { - public void ReceiveTicketChangeNotification(TicketChange ticketChange) - { - // update local datastore (datastore omitted in demo implementation) - Console.WriteLine($"{nameof(TicketResellerService)} notified " + - $"of ticket change: artist {ticketChange.ArtistId}, amount {ticketChange.Amount}"); - } - } +/// +/// ConcreteObserver +/// +public class TicketResellerService : ITicketChangeListener +{ + public void ReceiveTicketChangeNotification(TicketChange ticketChange) => + // update local datastore (datastore omitted in demo implementation) + Console.WriteLine($"{nameof(TicketResellerService)} notified " + + $"of ticket change: artist {ticketChange.ArtistId}, amount " + + $"{ticketChange.Amount}"); +} - /// - /// ConcreteObserver - /// - public class TicketStockService : ITicketChangeListener - { - public void ReceiveTicketChangeNotification(TicketChange ticketChange) - { - // update local datastore (datastore omitted in demo implementation) - Console.WriteLine($"{nameof(TicketStockService)} notified " + - $"of ticket change: artist {ticketChange.ArtistId}, amount {ticketChange.Amount}"); - } - } +/// +/// ConcreteObserver +/// +public class TicketStockService : ITicketChangeListener +{ + public void ReceiveTicketChangeNotification(TicketChange ticketChange) => + // update local datastore (datastore omitted in demo implementation) + Console.WriteLine($"{nameof(TicketStockService)} notified " + + $"of ticket change: artist {ticketChange.ArtistId}, amount " + + $"{ticketChange.Amount}"); } diff --git a/Finished sample/Observer/Program.cs b/Finished sample/Observer/Program.cs index 4b1bfe0..e363147 100644 --- a/Finished sample/Observer/Program.cs +++ b/Finished sample/Observer/Program.cs @@ -1,5 +1,7 @@ using Observer; +Console.Title = "Observer"; + TicketStockService ticketStockService = new(); TicketResellerService ticketResellerService = new(); OrderService orderService = new(); @@ -11,8 +13,12 @@ // notify orderService.CompleteTicketSale(1, 2); +Console.WriteLine(); + // remove one observer orderService.RemoveObserver(ticketResellerService); // notify orderService.CompleteTicketSale(2, 4); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Prototype/Implementation.cs b/Finished sample/Prototype/Implementation.cs index 7449d0e..94d97df 100644 --- a/Finished sample/Prototype/Implementation.cs +++ b/Finished sample/Prototype/Implementation.cs @@ -1,74 +1,53 @@ using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; -using System.Threading.Tasks; -namespace Prototype -{ - /// - /// Prototype abstract class - /// - public abstract class Person - { - public abstract string Name { get; set; } - - public abstract Person Clone(bool deepClone); - - } +namespace Prototype; - /// - /// ConcretePrototype1 - /// - public class Employee : Person - { - public Manager Manager { get; set; } - public override string Name { get; set; } - - public Employee(string name, Manager manager) - { - Name = name; - Manager = manager; - } +/// +/// Prototype +/// +public abstract class Person +{ + public abstract string Name { get; set; } - public override Person Clone(bool deepClone = false) - { - if (deepClone) - { - var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; - var objectAsJson = JsonConvert.SerializeObject(this, typeof(Employee), settings); - return JsonConvert.DeserializeObject(objectAsJson, settings); - } + public abstract Person Clone(bool deepClone); +} +/// +/// ConcretePrototype1 +/// +public class Manager : Person +{ + public override string Name { get; set; } - return (Person)MemberwiseClone(); - } - } + public Manager(string name) => Name = name; - /// - /// ConcretePrototype2 - /// - public class Manager : Person + public override Person Clone(bool deepClone = false) { - public override string Name { get; set; } - - public Manager(string name) + if (deepClone) { - Name = name; + var objectAsJson = JsonConvert.SerializeObject(this); + return JsonConvert.DeserializeObject(objectAsJson)!; } - public override Person Clone(bool deepClone = false) - { - if (deepClone) - { - var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; - var objectAsJson = JsonConvert.SerializeObject(this, typeof(Manager), settings); - return JsonConvert.DeserializeObject(objectAsJson, settings); - } - - return (Person)MemberwiseClone(); - } + return (Person)MemberwiseClone(); } } + +/// +/// ConcretePrototype2 +/// +public class Employee : Person +{ + public Manager Manager { get; set; } + public override string Name { get; set; } + + public Employee(string name, Manager manager) + { + Name = name; + Manager = manager; + } + + public override Person Clone(bool deepClone = false) => deepClone + ? JsonConvert.DeserializeObject(JsonConvert.SerializeObject(this))! + : (Person)MemberwiseClone(); +} \ No newline at end of file diff --git a/Finished sample/Prototype/Program.cs b/Finished sample/Prototype/Program.cs index 429c804..2a873c3 100644 --- a/Finished sample/Prototype/Program.cs +++ b/Finished sample/Prototype/Program.cs @@ -1,15 +1,19 @@ using Prototype; +Console.Title = "Prototype"; + var manager = new Manager("Cindy"); var managerClone = (Manager)manager.Clone(); Console.WriteLine($"Manager was cloned: {managerClone.Name}"); -var employee = new Employee("Kevin", manager); +var employee = new Employee("Kevin", managerClone); var employeeClone = (Employee)employee.Clone(true); -Console.WriteLine($"Employee was cloned: {employeeClone.Name}, with manager {employeeClone.Manager.Name}"); +Console.WriteLine($"Employee was cloned: {employeeClone.Name}," + + $" with manager {employeeClone.Manager.Name}"); // change the manager name -manager.Name = "Karen"; -Console.WriteLine($"Employee was cloned: {employeeClone.Name}, with manager {employeeClone.Manager.Name}"); +managerClone.Name = "Karen"; +Console.WriteLine($"Employee was cloned: {employeeClone.Name}, " + + $"with manager {employeeClone.Manager.Name}"); Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Prototype/Prototype.csproj b/Finished sample/Prototype/Prototype.csproj index 11b28f3..15a13e3 100644 --- a/Finished sample/Prototype/Prototype.csproj +++ b/Finished sample/Prototype/Prototype.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/Finished sample/Proxy/Implementation.cs b/Finished sample/Proxy/Implementation.cs index 1097957..982bdaa 100644 --- a/Finished sample/Proxy/Implementation.cs +++ b/Finished sample/Proxy/Implementation.cs @@ -1,101 +1,93 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Proxy; -namespace Proxy +/// +/// Subject +/// +public interface IDocument { - /// - /// RealSubject - /// - public class Document : IDocument - { - public string? Title { get; private set; } - public string? Content { get; private set; } - public int AuthorId { get; private set; } - public DateTimeOffset LastAccessed { get; private set; } - private string _fileName; - - public Document(string fileName) - { - _fileName = fileName; - LoadDocument(fileName); - } - - private void LoadDocument(string fileName) - { - Console.WriteLine("Executing expensive action: loading a file from disk"); - // fake loading... - Thread.Sleep(1000); + void DisplayDocument(); +} - Title = "An expensive document"; - Content = "Lots and lots of content"; - AuthorId = 1; - LastAccessed = DateTimeOffset.UtcNow; - } +/// +/// RealSubject +/// +public class Document : IDocument +{ + public string? Title { get; set; } + public string? Content { get; set; } + public int AuthorId { get; set; } + public DateTimeOffset LastAccessed { get; set; } + readonly string _fileName; - public void DisplayDocument() - { - Console.WriteLine($"Title: {Title}, Content: {Content}"); - } + public Document(string fileName) + { + _fileName = fileName; + LoadDocument(fileName); } - /// - /// Subject - /// - public interface IDocument + void LoadDocument(string fileName) { - void DisplayDocument(); + Console.WriteLine("Executing expensive action: loading a file from disk"); + // fake loading... + Thread.Sleep(1000); + + Title = "An expensive document"; + Content = "Lots and lots of content"; + AuthorId = 1; + LastAccessed = DateTimeOffset.UtcNow; } - /// - /// Proxy - /// - public class DocumentProxy : IDocument + public void DisplayDocument() => Console.WriteLine($"Title: {Title}, Content: {Content}"); +} + +/// +/// Proxy +/// +public class DocumentProxy : IDocument +{ + // avoid creating the document until we need it + readonly Lazy _document; + readonly string _fileName; + + public DocumentProxy(string fileName) { - // avoid creating the document until we need it - private Lazy _document; - private string _fileName; + _fileName = fileName; + _document = new Lazy(() => new Document(_fileName)); + } - public DocumentProxy(string fileName) - { - _fileName = fileName; - _document = new Lazy(() => new Document(_fileName)); - } + public void DisplayDocument() => _document.Value.DisplayDocument(); +} - public void DisplayDocument() - { - _document.Value.DisplayDocument(); - } +/// +/// Proxy +/// +public class ProtectedDocumentProxy : IDocument +{ + readonly string _fileName; + readonly string _userRole; + readonly DocumentProxy _documentProxy; + + public ProtectedDocumentProxy(string fileName, + string userRole) + { + _fileName = fileName; + _userRole = userRole; + _documentProxy = new DocumentProxy(_fileName); } - public class ProtectedDocumentProxy : IDocument + public void DisplayDocument() { - private string _fileName; - private string _userRole; - private DocumentProxy _documentProxy; + Console.WriteLine("Entering DisplayDocument " + + $"in {nameof(ProtectedDocumentProxy)}."); - public ProtectedDocumentProxy(string fileName, - string userRole) + if (_userRole != "Viewer") { - _fileName = fileName; - _userRole = userRole; - _documentProxy = new DocumentProxy(_fileName); + throw new UnauthorizedAccessException(); } - - public void DisplayDocument() - { - Console.WriteLine($"Entering DisplayDocument in {nameof(ProtectedDocumentProxy)}."); - - if (_userRole != "Viewer") - { - throw new UnauthorizedAccessException(); - } - _documentProxy.DisplayDocument(); + _documentProxy.DisplayDocument(); - Console.WriteLine($"Exiting DisplayDocument in {nameof(ProtectedDocumentProxy)}."); - } + Console.WriteLine("Exiting DisplayDocument " + + $"in {nameof(ProtectedDocumentProxy)}."); } } diff --git a/Finished sample/Proxy/Program.cs b/Finished sample/Proxy/Program.cs index 741215e..f40cad9 100644 --- a/Finished sample/Proxy/Program.cs +++ b/Finished sample/Proxy/Program.cs @@ -1,4 +1,5 @@ - +Console.Title = "Proxy"; + // without proxy Console.WriteLine("Constructing document."); var myDocument = new Proxy.Document("MyDocument.pdf"); @@ -28,3 +29,5 @@ myProtectedDocumentProxy = new Proxy.ProtectedDocumentProxy("MyDocument.pdf", "AnotherRole"); Console.WriteLine("Protected document proxy constructed."); myProtectedDocumentProxy.DisplayDocument(); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/ReadMe.txt b/Finished sample/ReadMe.txt new file mode 100644 index 0000000..8653c1c --- /dev/null +++ b/Finished sample/ReadMe.txt @@ -0,0 +1,14 @@ +My primary reason for raising this PR was to eliminate the noise distractions of excess warnings + +Some personal preferences caused significant style differences, so I commented those out ("#Dick ") in the .editorconfig to minimse extraneous changes +- feel free to uncomment to taste ! + +The added .editorconfig file resides here at solution-level. Unusually, it contains the setting +"dotnet_style_namespace_match_folder = false" +to address the 2 projects with peculiar namespace designs +1. Adapter teaches 2 alternates in the same folder but with different namespaces to distinguish + ClassAdapterImplementation.cs, ObjectAdapterImplementation.cs have same class definitions + if you set "dotnet_style_namespace_match_folder = true", the classes will collide + +2. Builder pattern originally had a "namespace BuilderPattern;", and Program.cs in the minimal style (i.e. implicit namespace) + but now simplified to match the containing folder structure, so Program needs an explicit "using Builder;" to link-in. diff --git a/Finished sample/Singleton/Implementation.cs b/Finished sample/Singleton/Implementation.cs index 929a610..a7c3ac8 100644 --- a/Finished sample/Singleton/Implementation.cs +++ b/Finished sample/Singleton/Implementation.cs @@ -1,47 +1,27 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Singleton; -namespace Singleton +/// +/// Singleton +/// +public class Logger { - /// - /// Singleton - /// - public class Logger - { - //private static Logger? _instance; + // Lazy + static readonly Lazy _lazyLogger + = new(() => new Logger()); - private static readonly Lazy _lazyLogger - = new Lazy(() => new Logger()); + // static Logger? _instance; - /// - /// Instance - /// - public static Logger Instance - { - get { return _lazyLogger.Value; } - //get - //{ - // if (_instance == null) - // { - // _instance = new Logger(); - // } - // return _instance; - //} - } - - protected Logger() - { - } + /// + /// Instance + /// + public static Logger Instance => _lazyLogger.Value;//if (_instance == null)//{// _instance = new Logger();//}//return _instance; - /// - /// SingletonOperation - /// - public void Log(string message) - { - Console.WriteLine($"Message to log: {message}"); - } + protected Logger() + { } + + /// + /// SingletonOperation + /// + public static void Log(string message) => Console.WriteLine($"Message to log: {message}"); } diff --git a/Finished sample/Singleton/Program.cs b/Finished sample/Singleton/Program.cs index bd57b5b..3782977 100644 --- a/Finished sample/Singleton/Program.cs +++ b/Finished sample/Singleton/Program.cs @@ -1,16 +1,20 @@ using Singleton; +Console.Title = "Singleton"; + // call the property getter twice -var instance1 = Logger.Instance; -var instance2 = Logger.Instance; +Logger instance1 = Logger.Instance; +Logger instance2 = Logger.Instance; if (instance1 == instance2 && instance2 == Logger.Instance) { Console.WriteLine("Instances are the same."); } -instance1.Log($"Message from {nameof(instance1)}"); +Logger.Log($"Message from {nameof(instance1)}"); // or -instance1.Log($"Message from {nameof(instance2)}"); +Logger.Log($"Message from {nameof(instance2)}"); // or -Logger.Instance.Log($"Message from {nameof(Logger.Instance)}"); \ No newline at end of file +Logger.Log($"Message from {nameof(Logger.Instance)}"); + +Console.ReadLine(); \ No newline at end of file diff --git a/Finished sample/State/Implementation.cs b/Finished sample/State/Implementation.cs index 36c7db6..a32749d 100644 --- a/Finished sample/State/Implementation.cs +++ b/Finished sample/State/Implementation.cs @@ -1,169 +1,136 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace State; -namespace State +/// +/// State +/// +public abstract class BankAccountState { - /// - /// State - /// - public abstract class BankAccountState + public BankAccount BankAccount { get; protected set; } = null!; + public decimal Balance { get; protected set; } + + public abstract void Deposit(decimal amount); + public abstract void Withdraw(decimal amount); +} + +/// +/// ConcreteState +/// +public class GoldState : BankAccountState +{ + public GoldState(decimal balance, BankAccount bankAccount) { - public BankAccount BankAccount { get; protected set; } = null!; - public decimal Balance { get; protected set; } + Balance = balance; + BankAccount = bankAccount; + } - public abstract void Deposit(decimal amount); - public abstract void Withdraw(decimal amount); + public override void Deposit(decimal amount) + { + Console.WriteLine($"In {GetType()}, depositing " + + $"{amount} + 10% bonus: {amount / 10}"); + Balance += amount + amount / 10; } - /// - /// ConcreteState - /// - public class OverdrawnState : BankAccountState + public override void Withdraw(decimal amount) { - public OverdrawnState(decimal balance, BankAccount bankAccount) + Console.WriteLine($"In {GetType()}, withdrawing {amount} from {Balance}"); + // change state to overdrawn when withdrawing results in less than zero + Balance -= amount; + if (Balance is < 1000 and >= 0) { - Balance = balance; - BankAccount = bankAccount; + // change state to regular + BankAccount.BankAccountState = new RegularState(Balance, BankAccount); } - - /// - /// Handle a deposit - /// - public override void Deposit(decimal amount) + else if (Balance < 0) { - Console.WriteLine($"In {GetType()}, depositing {amount}"); - Balance += amount; - if (Balance >= 0) - { - // change state to regular - BankAccount.BankAccountState = new RegularState(Balance, BankAccount); - } + // change state to overdrawn + BankAccount.BankAccountState = new OverdrawnState(Balance, BankAccount); } + } +} - /// - /// Handle withdrawing - /// - public override void Withdraw(decimal amount) - { - // cannot withdraw - Console.WriteLine($"In {GetType()}, cannot withdraw, balance {Balance}"); - } +/// +/// ConcreteState +/// +public class RegularState : BankAccountState +{ + public RegularState(decimal balance, BankAccount bankAccount) + { + Balance = balance; + BankAccount = bankAccount; } - /// - /// ConcreteState - /// - public class RegularState : BankAccountState + public override void Deposit(decimal amount) { - public RegularState(decimal balance, BankAccount bankAccount) + Console.WriteLine($"In {GetType()}, depositing {amount}"); + Balance += amount; + if (Balance >= 1000) { - Balance = balance; - BankAccount = bankAccount; + // change state to gold + BankAccount.BankAccountState = new GoldState(Balance, BankAccount); } + } - /// - /// Handle a deposit - /// - public override void Deposit(decimal amount) + public override void Withdraw(decimal amount) + { + Console.WriteLine($"In {GetType()}, withdrawing {amount} from {Balance}"); + // change state to overdrawn when withdrawing results in less than zero + Balance -= amount; + if (Balance < 0) { - Console.WriteLine($"In {GetType()}, depositing {amount}"); - Balance += amount; - if (Balance >= 1000) - { - // change state to gold - BankAccount.BankAccountState = new GoldState(Balance, BankAccount); - } + // change state to overdrawn + BankAccount.BankAccountState = new OverdrawnState(Balance, BankAccount); } + } +} - /// - /// Handle withdrawing - /// - public override void Withdraw(decimal amount) - { - Console.WriteLine($"In {GetType()}, withdrawing {amount} from {Balance}"); - // change state to overdrawn when withdrawing results in less than zero - Balance -= amount; - if (Balance < 0) - { - // change state to overdrawn - BankAccount.BankAccountState = new OverdrawnState(Balance, BankAccount); - } - } +/// +/// ConcreteState +/// +public class OverdrawnState : BankAccountState +{ + public OverdrawnState(decimal balance, BankAccount bankAccount) + { + Balance = balance; + BankAccount = bankAccount; } - /// - /// ConcreteState - /// - public class GoldState : BankAccountState + public override void Deposit(decimal amount) { - public GoldState(decimal balance, BankAccount bankAccount) + Console.WriteLine($"In {GetType()}, depositing {amount}"); + Balance += amount; + if (Balance >= 0) { - Balance = balance; - BankAccount = bankAccount; + // change state to regular + BankAccount.BankAccountState = new RegularState(Balance, BankAccount); } + } - /// - /// Handle a deposit - /// - public override void Deposit(decimal amount) - { - Console.WriteLine($"In {GetType()}, depositing {amount} + 10% bonus: {amount/10}"); - Balance += amount + (amount/10); - } + public override void Withdraw(decimal amount) => + // cannot withdraw + Console.WriteLine($"In {GetType()}, cannot withdraw, balance {Balance}"); +} - /// - /// Handle withdrawing - /// - public override void Withdraw(decimal amount) - { - Console.WriteLine($"In {GetType()}, withdrawing {amount} from {Balance}"); - // change state to overdrawn when withdrawing results in less than zero - Balance -= amount; - if (Balance < 1000 && Balance >= 0) - { - // change state to regular - BankAccount.BankAccountState = new RegularState(Balance, BankAccount); - } - else if (Balance < 0) - { - // change state to overdrawn - BankAccount.BankAccountState = new OverdrawnState(Balance, BankAccount); - } - } - } +/// +/// Context +/// +public class BankAccount +{ + public BankAccountState BankAccountState { get; set; } + public decimal Balance => BankAccountState.Balance; + + public BankAccount() => BankAccountState = new RegularState(200, this); /// - /// Context + /// Request a deposit /// - public class BankAccount - { - public BankAccountState BankAccountState { get; set; } - public decimal Balance { get { return BankAccountState.Balance; } } + public void Deposit(decimal amount) => + // let the current state handle the deposit + BankAccountState.Deposit(amount); - public BankAccount() - { - BankAccountState = new RegularState(200, this); - } - - /// - /// Request a deposit - /// - public void Deposit(decimal amount) - { - // let the current state handle the deposit - BankAccountState.Deposit(amount); - } - - /// - /// Request a withdrawal - /// - public void Withdraw(decimal amount) - { - // let the current state handle the withdrawel - BankAccountState.Withdraw(amount); - } - } -} + /// + /// Request a withdrawal + /// + public void Withdraw(decimal amount) => + // let the current state handle the withdrawel + BankAccountState.Withdraw(amount); +} \ No newline at end of file diff --git a/Finished sample/State/Program.cs b/Finished sample/State/Program.cs index d9f8fc6..9d99427 100644 --- a/Finished sample/State/Program.cs +++ b/Finished sample/State/Program.cs @@ -1,5 +1,7 @@ using State; +Console.Title = "State"; + BankAccount bankAccount = new(); bankAccount.Deposit(100); bankAccount.Withdraw(500); @@ -13,4 +15,5 @@ // should transition to regular bankAccount.Deposit(3000); // should still be in regular -bankAccount.Deposit(100); \ No newline at end of file +bankAccount.Deposit(100); +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/Strategy/Implementation.cs b/Finished sample/Strategy/Implementation.cs index 118a283..a9f6f55 100644 --- a/Finished sample/Strategy/Implementation.cs +++ b/Finished sample/Strategy/Implementation.cs @@ -1,71 +1,61 @@ -namespace Strategy +namespace Strategy; + +/// +/// Strategy +/// +public interface IExportService { - /// - /// Strategy - /// - public interface IExportService - { - void Export(Order order); - } + void Export(Order order); +} - /// - /// ConcreteStrategy - /// - public class JsonExportService : IExportService - { - public void Export(Order order) - { - Console.WriteLine($"Exporting {order.Name} to Json."); - } - } +/// +/// ConcreteStrategy +/// +public class JsonExportService : IExportService +{ + public void Export(Order order) => Console.WriteLine($"Exporting {order.Name} to Json."); +} - /// - /// ConcreteStrategy - /// - public class XMLExportService : IExportService - { - public void Export(Order order) - { - Console.WriteLine($"Exporting {order.Name} to XML."); - } - } +/// +/// ConcreteStrategy +/// +public class XMLExportService : IExportService +{ + public void Export(Order order) => Console.WriteLine($"Exporting {order.Name} to XML."); +} + +/// +/// ConcreteStrategy +/// +public class CSVExportService : IExportService +{ + public void Export(Order order) => Console.WriteLine($"Exporting {order.Name} to CSV."); +} + +/// +/// Context +/// +public class Order +{ + public string Customer { get; set; } + public int Amount { get; set; } + public string Name { get; set; } + public string? Description { get; set; } - /// - /// ConcreteStrategy - /// - public class CSVExportService : IExportService + public Order(string customer, int amount, string name) { - public void Export(Order order) - { - Console.WriteLine($"Exporting {order.Name} to CSV."); - } + Customer = customer; + Amount = amount; + Name = name; } - - /// - /// Context - /// - public class Order - { - public string Customer { get; set; } - public int Amount { get; set; } - public string Name { get; set; } - public string? Description { get; set; } - public Order(string customer, int amount, string name) + public void Export(IExportService exportService) + { + if (exportService is null) { - Customer = customer; - Amount = amount; - Name = name; + throw new ArgumentNullException(nameof(exportService)); } - public void Export(IExportService exportService) - { - if (exportService is null) - { - throw new ArgumentNullException(nameof(exportService)); - } - - exportService.Export(this); - } + exportService.Export(this); } } diff --git a/Finished sample/Strategy/Program.cs b/Finished sample/Strategy/Program.cs index 794591f..b5cc766 100644 --- a/Finished sample/Strategy/Program.cs +++ b/Finished sample/Strategy/Program.cs @@ -1,5 +1,9 @@ using Strategy; +Console.Title = "Strategy"; + var order = new Order("Marvin Software", 5, "Visual Studio License"); order.Export(new CSVExportService()); -order.Export(new JsonExportService()); \ No newline at end of file +order.Export(new JsonExportService()); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/TemplateMethod/Implementation.cs b/Finished sample/TemplateMethod/Implementation.cs index d42d7f1..5cef5cf 100644 --- a/Finished sample/TemplateMethod/Implementation.cs +++ b/Finished sample/TemplateMethod/Implementation.cs @@ -1,67 +1,44 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace TemplateMethod; -namespace TemplateMethod -{ - /// - /// AbstractClass - /// - public abstract class MailParser - { - public virtual void FindServer() - { - Console.WriteLine("Finding server..."); - } - - public abstract void AuthenticateToServer(); - +/// +/// AbstractClass +/// +public abstract class MailParser +{ + public virtual void FindServer() => Console.WriteLine("Finding server..."); - public virtual string ParseHtmlMailBody(string identifier) - { - Console.WriteLine("Parsing HTML mail body..."); - return $"This is the body of mail with id {identifier}"; - } + public abstract void AuthenticateToServer(); - /// - /// Template method - /// - public string ParseMailBody(string identifier) - { - Console.WriteLine("Parsing mail body (in template method)..."); - FindServer(); - AuthenticateToServer(); - return ParseHtmlMailBody(identifier); - } - } - - public class ExchangeMailParser : MailParser + public static string ParseHtmlMailBody(string identifier) { - public override void AuthenticateToServer() - { - Console.WriteLine("Connecting to Exchange"); - } + Console.WriteLine("Parsing HTML mail body..."); + return $"This is the body of mail with id {identifier}"; } - public class ApacheMailParser : MailParser + /// + /// Template method + /// + public string ParseMailBody(string identifier) { - public override void AuthenticateToServer() - { - Console.WriteLine("Connecting to Apache"); - } + Console.WriteLine("Parsing mail body (in template method)..."); + FindServer(); + AuthenticateToServer(); + return ParseHtmlMailBody(identifier); } +} - public class EudoraMailParser : MailParser - { - public override void FindServer() - { - Console.WriteLine("Finding Eudora server through a custom algorithm..."); - } - public override void AuthenticateToServer() - { - Console.WriteLine("Connecting to Eudora"); - } - } +public class ExchangeMailParser : MailParser +{ + public override void AuthenticateToServer() => Console.WriteLine("Connecting to Exchange"); +} + +public class ApacheMailParser : MailParser +{ + public override void AuthenticateToServer() => Console.WriteLine("Connecting to Apache"); +} + +public class EudoraMailParser : MailParser +{ + public override void FindServer() => Console.WriteLine("Finding Eudora server through a custom algorithm..."); + public override void AuthenticateToServer() => Console.WriteLine("Connecting to Eudora"); } diff --git a/Finished sample/TemplateMethod/Program.cs b/Finished sample/TemplateMethod/Program.cs index f4de8ca..6ccf979 100644 --- a/Finished sample/TemplateMethod/Program.cs +++ b/Finished sample/TemplateMethod/Program.cs @@ -1,5 +1,7 @@ using TemplateMethod; +Console.Title = "Template Method"; + ExchangeMailParser exchangeMailParser = new(); Console.WriteLine(exchangeMailParser.ParseMailBody("bf3a298c-9990-4b02-873d-3d3c98ad16d2")); Console.WriteLine(); @@ -9,4 +11,6 @@ Console.WriteLine(); EudoraMailParser eudoraMailParser = new(); -Console.WriteLine(eudoraMailParser.ParseMailBody("789fe935-ced2-4fbd-865b-172909560a93")); \ No newline at end of file +Console.WriteLine(eudoraMailParser.ParseMailBody("789fe935-ced2-4fbd-865b-172909560a93")); + +Console.ReadKey(); \ No newline at end of file diff --git a/Finished sample/TemplateMethod/TemplateMethod - Backup.csproj b/Finished sample/TemplateMethod/TemplateMethod - Backup.csproj new file mode 100644 index 0000000..f02677b --- /dev/null +++ b/Finished sample/TemplateMethod/TemplateMethod - Backup.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/Finished sample/Visitor/Implementation.cs b/Finished sample/Visitor/Implementation.cs index 6c507f0..b9a5d2a 100644 --- a/Finished sample/Visitor/Implementation.cs +++ b/Finished sample/Visitor/Implementation.cs @@ -1,170 +1,135 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Visitor; -namespace Visitor +/// +/// ConcreteElement +/// +public class Customer : IElement { - ///// - ///// Visitor - ///// - //public interface IVisitor - //{ - // void VisitCustomer(Customer customer); - // void VisitEmployee(Employee employee); - //} + public decimal AmountOrdered { get; } + public decimal Discount { get; set; } + public string Name { get; } - /// - /// Visitor (alternative) - /// - public interface IVisitor + public Customer(string name, decimal amountOrdered) { - void Visit(IElement element); + Name = name; + AmountOrdered = amountOrdered; } - /// - /// Element - /// - public interface IElement + public void Accept(IVisitor visitor) { - void Accept(IVisitor visitor); + // visitor.VisitCustomer(this); + visitor.Visit(this); + Console.WriteLine($"Visited {nameof(Customer)} {Name}, " + + $"discount given: {Discount}"); } +} - /// - /// ConcreteElement - /// - public class Customer : IElement - { - public decimal AmountOrdered { get; private set; } - public decimal Discount { get; set; } - public string Name { get; private set; } +/// +/// ConcreteElement +/// +public class Employee : IElement +{ + public int YearsEmployed { get; } + public decimal Discount { get; set; } + public string Name { get; } - public Customer(string name, decimal amountOrdered) - { - Name = name; - AmountOrdered = amountOrdered; - } - - public void Accept(IVisitor visitor) - { - // alternative - // visitor.VisitCustomer(this); - visitor.Visit(this); - Console.WriteLine($"Visited {nameof(Customer)} {Name}, discount given: {Discount}"); - } + public Employee(string name, int yearsEmployed) + { + Name = name; + YearsEmployed = yearsEmployed; } - /// - /// ConcreteElement - /// - public class Employee : IElement + public void Accept(IVisitor visitor) { - public int YearsEmployed { get; private set; } - public decimal Discount { get; set; } - public string Name { get; private set; } - - public Employee(string name, int yearsEmployed) - { - Name = name; - YearsEmployed = yearsEmployed; - } - - public void Accept(IVisitor visitor) - { - // alternative - // visitor.VisitEmployee(this); - visitor.Visit(this); - Console.WriteLine($"Visited {nameof(Employee)} {Name}, discount given: {Discount}"); - } + // visitor.VisitEmployee(this); + visitor.Visit(this); + Console.WriteLine($"Visited {nameof(Employee)} " + + $"{Name}, discount given: {Discount}"); } +} - ///// - ///// ConcreteVisitor - ///// - //public class DiscountVisitor : IVisitor - //{ - // public decimal TotalDiscountGiven { get; set; } +///// +///// Visitor +///// +//public interface IVisitor +//{ +// void VisitCustomer(Customer customer); +// void VisitEmployee(Employee employee); +//} + +/// +/// Visitor (alternative) +/// +public interface IVisitor +{ + void Visit(IElement element); +} - // public void VisitCustomer(Customer customer) - // { - // // percentage of total amount - // var discount = customer.AmountOrdered / 10; - // // set it on the customer - // customer.Discount = discount; - // // add it to the total amount - // TotalDiscountGiven += discount; - // } +/// +/// Element +/// +public interface IElement +{ + void Accept(IVisitor visitor); +} - // public void VisitEmployee(Employee employee) - // { - // // fixed value depending on the amount of years employed - // var discount = employee.YearsEmployed < 10 ? 100 : 200; - // // set it on the employee - // employee.Discount = discount; - // // add it to the total amount - // TotalDiscountGiven += discount; - // } - //} +/// +/// ConcreteVisitor +/// +public class DiscountVisitor : IVisitor +{ + public decimal TotalDiscountGiven { get; set; } - /// - /// ConcreteVisitor (alternative) - /// - public class DiscountVisitor : IVisitor + public void Visit(IElement element) { - public decimal TotalDiscountGiven { get; set; } - - public void Visit(IElement element) + if (element is Customer customer) { - if (element is Customer) - { - VisitCustomer((Customer)element); - } - else if (element is Employee) - { - VisitEmployee((Employee)element); - } + VisitCustomer(customer); } - - private void VisitCustomer(Customer customer) + else if (element is Employee employee) { - // percentage of total amount - var discount = customer.AmountOrdered / 10; - // set it on the customer - customer.Discount = discount; - // add it to the total amount - TotalDiscountGiven += discount; + VisitEmployee(employee); } + } - private void VisitEmployee(Employee employee) - { - // fixed value depending on the amount of years employed - var discount = employee.YearsEmployed < 10 ? 100 : 200; - // set it on the employee - employee.Discount = discount; - // add it to the total amount - TotalDiscountGiven += discount; - } + void VisitCustomer(Customer customer) + { + // percentage of total amount + var discount = customer.AmountOrdered / 10; + // set it on the customer + customer.Discount = discount; + // add it to the total amount + TotalDiscountGiven += discount; } - /// - /// ObjectStructure - /// - public class Container + void VisitEmployee(Employee employee) { - public List Employees { get; set; } = new(); - public List Customers { get; set; } = new(); + // fixed value depending on the amount of years employed + var discount = employee.YearsEmployed < 10 ? 100 : 200; + // set it on the employee + employee.Discount = discount; + // add it to the total amount + TotalDiscountGiven += discount; + } +} + +/// +/// ObjectStructure +/// +public class Container +{ + public List Employees { get; set; } = new(); + public List Customers { get; set; } = new(); - public void Accept(IVisitor visitor) + public void Accept(IVisitor visitor) + { + foreach (Employee employee in Employees) + { + employee.Accept(visitor); + } + foreach (Customer customer in Customers) { - foreach (var employee in Employees) - { - employee.Accept(visitor); - } - foreach (var customer in Customers) - { - customer.Accept(visitor); - } + customer.Accept(visitor); } } -} +} \ No newline at end of file diff --git a/Finished sample/Visitor/Program.cs b/Finished sample/Visitor/Program.cs index 4d28a5a..be089bc 100644 --- a/Finished sample/Visitor/Program.cs +++ b/Finished sample/Visitor/Program.cs @@ -1,7 +1,10 @@ using Visitor; -// create container & add conrete elements +Console.Title = "Visitor"; + +// create container & add concrete elements var container = new Container(); + container.Customers.Add(new Customer("Sophie", 500)); container.Customers.Add(new Customer("Karen", 1000)); container.Customers.Add(new Customer("Sven", 800)); @@ -15,4 +18,6 @@ container.Accept(discountVisitor); // write out gathered amount -Console.WriteLine($"Total discount: {discountVisitor.TotalDiscountGiven}"); \ No newline at end of file +Console.WriteLine($"Total discount: {discountVisitor.TotalDiscountGiven}"); + +Console.ReadKey(); \ No newline at end of file