简体   繁体   English

我可以使用什么设计模式来完成以下操作

[英]What Design Pattern can I use to accomplish the following

In my code I would like to be able to "build" an object like this.. 在我的代码中,我希望能够“构建”这样的对象..

// Build a Person instance and add types that the person is
Person person = new Person(); 
person = new Leader(person);
person = new Secretary(person);
person = new Parent(person);

The goal of the code above is to build a base object that has multiple types added to it - a Leader, a Secretary, and a Parent. 上面代码的目标是构建一个添加了多个类型的基础对象 - Leader,Secretary和Parent。 Specifically, my goal is to be able to build a base object (Person) and make that object be able to take on multiple types simultaneously such that the following condition would return true: 具体来说,我的目标是能够构建一个基础对象(Person)并使该对象能够同时处理多个类型,以便以下条件返回true:

((person is Leader) && (person is Secretary) && (person is Parent)) <<<-- Returns True ((人是领导)&&(人是秘书)&&(人是父母))<<< - 返回True

Is there a Design Pattern that I can use to accomplish this? 我可以使用设计模式来实现这一目标吗?

The problem with the above examples is that the person object can only be one sub-type at a time and all previous instantiations are, apparently, overwritten. 上述示例的问题在于人对象一次只能是一个子类型,并且显然所有先前的实例都被覆盖。 In other words, the only condition that would return true is (person is Parent) since it is the last in line. 换句话说,唯一会返回true的条件是(person is Parent)因为它是最后一行。

Note: I initially thought the Decorator Pattern sounded like what I needed, but from what I read, the Decorator Pattern seems to be more about adding behavior to an object as apposed to extending its type. 注意:我最初认为装饰器模式听起来像我需要的,但从我读到的,装饰器模式似乎更多的是添加行为到对象扩展其类型。

Update 更新

For clarity - I suppose I should have mentioned in my OP that I am trying to create a design with my classes that mirrors the design of my RDBM. 为清楚起见 - 我想我应该在我的OP中提到我正在尝试用我的类创建一个反映我的RDBM设计的设计。

So, continuing on with the original example - 所以,继续原始的例子 -

My RDBM contains the tables Person, Leader, Secretary, and Parent. 我的RDBM包含表Person,Leader,Secretary和Parent。 The Person table has the PersonId PK and the others have a PersonId FK . Person表具有PersonId PK ,其他具有PersonId FK

When I execute a query that joins all the tables, I can determine which Person records have a non-null FK in the sub-tables. 当我执行一个连接所有表的查询时,我可以确定哪些Person记录在子表中具有非空FK。

Flattened out, a query result might look like this: 展平,查询结果可能如下所示:

PersonId | FirstName | LeaderId | LeaderApproved | SecretaryId | SecretaryFavPencil | ParentId  
----------------------------------------------------------------------------------------------
100      | Frank     | 34       | True           | Null        | Null               | 700
----------------------------------------------------------------------------------------------
743      | Dweezil   | 43       | False          | 343         | Ticon              | 654
----------------------------------------------------------------------------------------------
567      | Ahmet     | Null     | Null           | Null        | Null               | 123
----------------------------------------------------------------------------------------------

The resultant table above shows us that Frank is a Leader and a Parent; 上面的结果表告诉我们Frank是领导者和父母; Dweezil is a Leader, a Secretary, and a Parent, an Ahmet is just a Parent. Dweezil是领导者,秘书和父母,Ahmet只是父母。

In my Data Access Layer, I am using one query to retrieve all the Person records along with their associated FK'd tables, instantiate Person objects, and then return a List to the caller. 在我的数据访问层中,我使用一个查询来检索所有Person记录及其关联的FK'd表,实例化Person对象,然后将List返回给调用者。

The caller can then do whatever it is he needs to do with the Person objects, but he is able to check all the types that a Person object is via (person is Leader) . 然后调用者可以执行他需要对Person对象执行的任何操作,但是他能够检查Person对象通过的所有类型(person is Leader)

I think the Strategy pattern should fit your needs. 我认为战略模式应该符合您的需求。
Your question does not specify all of your requirements, but you can have an object that is a composite of types such as Secretary Leader and Parent , then at run time you will have to choose which one of them is the chosen strategy at the moment. 您的问题没有指定您的所有要求,但您可以拥有一个对象类型的组合,例如Secretary LeaderParent ,然后在运行时您必须选择其中哪一个是当前所选择的策略。

Also, assuming all of the types have some kind of a common interface which the composed object will implement as well you can keep the instances in an array, something like: 此外,假设所有类型都有某种组合对象将实现的公共接口,您可以将实例保留在数组中,如:

IPerson[] _rolles  = 
                 new IPerson[]{new Leader(this), new Secretary(this), new Parent(this)};

And have a method for type checking which will look something like this: 并有一个类型检查方法,看起来像这样:

        public bool Is(Type type)
        {
            return this.Is(new Type[]{type});
        }

        public bool Is(Type[] types)
        {
            bool isType = true;
            foreach (var type in types)
            {
                isType &= this._rolles.Any(r => r.GetType() == type);
            }
            return isType;
        }

Edit: 编辑:

A fuller code example: 更完整的代码示例:

    public class Person : IPerson
    {

        List<IPerson> _rolles;
        IPerson _chosenStrategy;


        public Person()
        {
            this._rolles =
                new List<IPerson>() { new Leader(this), new Secretary(this), new Parent(this) };
            this._chosenStrategy = this._rolles[0];
        }

        public void AddRole(Func<Person, IPerson> creator) {
              IPerson newRole = creator(this)
              //You can choose to remove duplicate roles by uncommenting the following line:
              //this.RemoveRole(newRole.GetType());
              this._rolles.Add(newRole);
        }

        public void RemoveRole(Type type) {
              this._rolles.RemoveAll(r => r.GetType() == type);
        }


         public bool Is(Type type)
        {
            return this.Is(new Type[]{type});
        }

        public bool Is(Type[] types)
        {
            bool isType = true;
            foreach (var type in types)
            {
                isType &= this._rolles.Any(r => r.GetType() == type);
            }
            return isType;
        }

        private void SetStrategy(Type type)
        {
            this._chosenStrategy = this._rolles.Where(r => r.GetType() == type).FirstOrDefault();
        }

        /*Rest of Implementation goes here*/
    }

And the other required classes: 以及其他所需的课程:

    interface IPerson
    {
        /*Implementation goes here*/
    }
    class Leader : IPerson
    {
        public Leader(IPerson p)
        {

        }
        /*Rest of Implementation goes here*/
    }

    class Parent : IPerson
    {
        public Parent(IPerson p)
        {

        }
    }

    class Secretary : IPerson
    {
        public Secretary(IPerson p)
        {

        }
        /*Rest of Implementation goes here*/
    }

((person is Leader) && (person is Secretary) && (person is Parent)) <<<-- Returns True ((人是领导)&&(人是秘书)&&(人是父母))<<< - 返回True

Technically this is possible, but only if a Leader is one of the other two, and one of the other two is always one of the others. 从技术上讲,这是可能的,但前提是领导者是另外两个中的一个,而另外两个中的一个总是其中一个。

public Leader : Person { }
public Secretary : Leader { }
public Parent : Secretary/Leader { }

If this isn't always the case, then your specific request is impossible using that specific code. 如果情况并非总是如此,则使用该特定代码无法获得特定请求。

If you're dead set in using is , then alternatively, you could use interfaces: 如果您已经设置使用is ,则可以使用接口:

((person is ILeader) && (person is ISecretary) && (person is IParent)) <<<-- Returns True ((人是ILeader)&&(人是ISecretary)&&(人是IParent))<<< - 返回True

public inteface IPerson;
public inteface ILeader : IPerson;
public interface ISecretary : IPerson;
public interface IParent : IPerson;

public Leader : ILeader;
public Secretary : ISecretary;
public Parent : IParent;

public LeaderSecretary : ILeader, ISecretary;
public LeaderParent : ILeader, IParent;
public SecretaryParent: ISecretary, IParent,
public LeaderSecretaryParent: ILeader, ISecretary, IParent;

But seriously do not do this. 严重的是不要这样做。

First. 第一。 Classes in OOP are primarily meant as expressing behavior. OOP中的类主要用于表达行为。 You saying " seems to be more about adding behavior to an object" implies that your classes are not about behavior. 你说“似乎更多的是为对象添加行为”意味着你的类与行为无关。 If they are not, then what are they about? 如果他们不是,那么他们是关于什么的?

((person is Leader) && (person is Secretary) && (person is Parent))

Types in OOP are meant for compiler. OOP中的类型适用于编译器。 Using type as part of program logic is considered wrong practice in OOP programming. 在OOP编程中,使用类型作为程序逻辑的一部分被认为是错误的实践。 Also, following this code is clearly a behavior. 此外,遵循此代码显然是一种行为。 So, instead of trying to mess around with types, you should sum up your requirements and figure out a design, that does satisfy your requirements. 因此,您应该总结您的要求并找出满足您要求的设计,而不是试图弄乱类型。 In your case, first requirement is ability to change "role" of a person at runtime. 在您的情况下,第一个要求是能够在运行时更改人员的“角色”。 If this doesn't change the behavior, simple Enum is enough. 如果这不会改变行为,简单的Enum就足够了。 If there is behavior, then Strategy , maybe combined with Composite is possible. 如果有行为,那么策略 ,可能与Composite结合是可能的。 Second requirement is having behavior, that only executes, when person has multiple roles. 第二个要求是具有行为,仅在人具有多个角色时执行。 If you are using enum, then it is simple. 如果你使用枚举,那很简单。 But it becomes more complicated when you use strategy. 但是当你使用策略时它会变得更加复杂。 While I don't have exact solution, I think if you are going to have type checking, then it should be encapsulated inside some kind of "factory" that creates the behavior based on person and his roles. 虽然我没有确切的解决方案,但我认为如果您要进行类型检查,那么它应该封装在某种“工厂”中,该工厂根据人和他的角色创建行为。

我认为你需要的是装饰模式,你可以使用工厂和策略来帮助你... 希望这可以给你一个想法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM