处理将相似实体分组的设计模式

时间:2009-09-16 16:28:02

标签: c# java php design-patterns oop

在过去的几年里,我一直在处理我们在对象层次结构中遇到类似问题的项目,这些问题总是会导致问题。我很好奇,如果有人知道经典的OOP(Java,C#,PHP5等)设计模式可以优雅地处理这种情况。

假设我们有一个现有的系统。除其他外,该系统具有两种类型的实体,每种实体都用单独的类建模。我们说

  1. 客户

  2. 的SalesRepresentative

  3. 由于历史原因,这些类都不从相同的基类继承或共享公共接口。

    我看到的问题是,不可避免地会出现一个新功能,要求我们将Customer和SalesRepresentative视为相同类型的Object。我在过去看到这种处理的方式是创建一个包含两者成员变量的新类,然后每个方法将根据设置的不同对对象进行操作

    //pseudo PHPish code
    class Participator
    {
        public $customer;
        public $salesRepresentative;
    
        public function __construct($object)
        {
            if(object is instance of Customer)
            {
                $this->customer = $object;
            }
    
            if(object is instance of SalesRepresentative)
            {
                $this->salesRepresentative = $object;
            }           
        }
    
        public function doesSomething()
        {
    
            if($customer)
            {
                //We're a customer, do customer specific stuff
            }
            else if($salesRepresentative)
            {
                //We're a salesRepresentative, do sales 
                //representative specific stuff
            }           
        }
    }
    

    有没有更优雅的方式来处理这种情况?

3 个答案:

答案 0 :(得分:8)

也许这里可以使用Wrapper。创建一个Wrapper接口,说参与者指定新功能并为每个类构建具体的Wrappers,比如说实现新功能的CustomerWrapper和SalesRepresentativeWrapper。

然后简单地将对象包装在适当的包装器中,并编写以ParticipatorWrapper为目标的代码。

更新:Javaish代码:

interface ParticipatorWrapper{
    public void doSomething();
}

class CustomerWrapper implements ParticipatorWrapper{
    Customer customer;
    public void doSomething(){
       //do something with the customer
    }
}

class SaleREpresentativeWrapper implements ParticipatorWrapper{
    SaleRepresentative salesRepresentative;
    public void doSomething(){
       //do something with the salesRepresentative
    }

}

class ClientOfWrapper{
    public void mymethod(){
         ParticipatorWrapper p = new ParticipatorWrapper(new Customer());
         p.doSomething();
   }
}

答案 1 :(得分:2)

这是文森特答案的替代方案,采取了相反的方法。正如我在下面提到的那样,有一些缺点,但是您的具体问题可能会消除这些问题,我认为这种解决方案在这些情况下更简单(或者您可能希望使用此解决方案和Vincent的某些组合)。

不是包装类,而是在类中引入钩子,然后将它们传递给函数。如果你想要从两个类中使用相同的数据做同样的事情(我猜你是基于这两个类没有共享的超类),这是一个合理的选择。

这是使用Visitor而不是Wrapper。 Java是这样的:

public <Output> Output visit(Vistor<Output> v) {
return v.process(...all shared the fields in Customer/SalesRep...);
}

然后你有一个访问者界面,你的所有功能都继承了这个界面:

interface Visitor<Output> {
public Output process(...shared fields...);
}

有些方法可以删除传递给访问者的内容,但是需要引入新的类来指定要使用的输入,无论如何都要包装,所以你不妨使用Vincent的答案。

这个解决方案的缺点是如果你做了改变类字段结构的事情,你可以自己购买很多重构,这在Vincent的答案中不是问题。如果您对Customer / SalesRep实例中存储的数据进行修改,这个解决方案也会有所帮助,因为您实际上必须将这些数据包装在访问者中。

答案 2 :(得分:1)

我认为您可以将mixins的概念应用于您的课程,以获得您想要的功能。