首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >策略规范模式中最明确的规范

策略规范模式中最明确的规范
EN

Stack Overflow用户
提问于 2015-07-13 20:11:17
回答 1查看 243关注 0票数 0

假设我有很多业务逻辑,可以根据多种因素来确定应用程序的行为。而且,我有一些非常好的地方,我知道我可以用一个策略模式来代替行为。同时,考虑到我试图利用各种模式来解决一个问题

  • 战略模式
  • 规格模式
  • 工厂模式

是否可以使用规范模式来确定工厂的策略,并保留开放封闭原则?

我有一个工厂,我发现自己创建开关语句,就像以前的代码一样,选择正确的策略。这似乎适得其反。

我想把所有这些逻辑决策都推到规范上,但随后出现的问题是如何对规范进行排序或首先选择最明确的规范。

知道怎么解决这个问题吗?

EN

回答 1

Stack Overflow用户

发布于 2016-03-10 22:20:04

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;

using static BeyondOOP.Gender;

// having to make decisions based on logic
// control flow without all the nested if then
namespace BeyondOOP
{
    class Program
    {
        static void Main(string[] args)
        {
            var people = new List<Person>
            {
                new Person("Bill", new DateTime(1940, 10, 10), Male),
                new Person("Jill", new DateTime(1950, 10, 10), Female),
                new Person("Mary", new DateTime(2015, 10, 10), Female),
                new Person("Gary", new DateTime(1970, 10, 10), Male),
                new Person("Greg", new DateTime(1980, 10, 10), Male),
                new Person("Susan", new DateTime(2013, 10, 10), Female),
                new Person("Gabe", new DateTime(1999, 10, 10), Neutral),
                new Person("Barbie", new DateTime(2000, 10, 10), Female),
            };
            var greeter = new PersonGreeter();
            people.ForEach(greeter.Greet);
        }
    }

    // a little 'generics' flair
    // a 'predicate' is just a way
    // to predetermine true false
    interface IPredicate<T>
    {
        bool Matches(T value);
    }

    // this is just a simple DTO
    // Data transfer object, fancy for value container
    // it's just a way of passing values around
    class Person
    {
        public string Name { get; }
        public DateTime DateOfBirth { get; }
        public Gender Gender { get; }

        public Person(string name, DateTime dateOfBirth, Gender gender)
        {
            Name = name;
            DateOfBirth = dateOfBirth;
            Gender = gender;
        }
    }

    enum Gender { Male, Female, Neutral }

    // some prefabed predicates for 'Person'
    class OldManPredicate : IPredicate<Person>
    {
        public bool Matches(Person value) =>
            (DateTime.Now.Year - value.DateOfBirth.Year) >= 60 && 
                value.Gender == Gender.Male;
    }

    class MinorPredicate : IPredicate<Person>
    {
        public bool Matches(Person value) =>
            DateTime.Now.Year - value.DateOfBirth.Year < 18;
    }

    class ToddlerPredicate : IPredicate<Person>
    {
        public bool Matches(Person value) =>
            DateTime.Now.Year - value.DateOfBirth.Year > 2 &&
            DateTime.Now.Year - value.DateOfBirth.Year < 4;
    }

    class BabyPredicate : IPredicate<Person>
    {
        public bool Matches(Person value) =>
            DateTime.Now.Year - value.DateOfBirth.Year <= 2;
    }

    class TruePersonPredicate : IPredicate<Person>
    {
        public bool Matches(Person value) => true;
    }

    class GreetAction
    {
        public Func<Person,bool> Predicate { get; }
        public Func<Person,string> Messager { get; }

        public GreetAction(Func<Person, bool> predicate, 
            Func<Person, string> messager  )
        {
            Predicate = predicate;
            Messager = messager;
        }
    }
    class PersonGreeter
    {
        // someone may say that if you're using Func
        // why do you go through the trouble of the extra
        // classes. Predicate classes can be added freely
        // Only this factory class needs to be changed
        // and if I was to create a factory for the predicates 
        // and messagers then no changes would be neccessary
        private readonly List<GreetAction> _greetActions =
            new List<GreetAction>
            {
                // these have to be ordered
                // so they don't conflict or override
                // intended behavior
                // MinorPredicate is < 18 but babies and toddlers are also
                // less than 18, they need to preceed minors to work
                new GreetAction( new OldManPredicate().Matches, 
                    p => $"{p.Name}, you're getting up there!"),
                new GreetAction( new BabyPredicate().Matches,
                    p => $"{p.Name}, time to change the diaper!"),
                new GreetAction( new ToddlerPredicate().Matches,
                    p => $"{p.Name}, look, you're walking!"),
                new GreetAction( new MinorPredicate().Matches, 
                    p => $"{p.Name}, no, you may not have beer!"),
                // you need a default action
                // this is the same as a 'Null Pattern'
                new GreetAction( new TruePersonPredicate().Matches,
                    p => $"{p.Name}, hello there!"),
            }; 

        public void Greet(Person person) => 
            Console.WriteLine(_greetActions
                .First(p => p.Predicate(person))
                .Messager(person));
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31392519

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档