Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 如何着手解决这个问题(设计模式)_Design Patterns - Fatal编程技术网

Design patterns 如何着手解决这个问题(设计模式)

Design patterns 如何着手解决这个问题(设计模式),design-patterns,Design Patterns,我有一个计费系统,不同类型的客户有不同类型的折扣方案。对于给定的票据,应根据客户和产品的类型生成应付净额 而且也没有什么规则。比如: •如果用户是商店的员工,他可以获得30%的折扣 •如果用户是该商店的附属机构,则可获得10%的折扣 •如果用户已成为客户超过2年,则可获得5%的折扣 •账单上每100美元,将有5美元的折扣(例如,对于990美元,您将获得45美元的折扣) •基于百分比的折扣不适用于食品杂货 我脑子里几乎没有什么想法。第一个赌注是考虑装饰图案: Customer <<I

我有一个计费系统,不同类型的客户有不同类型的折扣方案。对于给定的票据,应根据客户和产品的类型生成应付净额

而且也没有什么规则。比如:

•如果用户是商店的员工,他可以获得30%的折扣

•如果用户是该商店的附属机构,则可获得10%的折扣

•如果用户已成为客户超过2年,则可获得5%的折扣

•账单上每100美元,将有5美元的折扣(例如,对于990美元,您将获得45美元的折扣)

•基于百分比的折扣不适用于食品杂货

我脑子里几乎没有什么想法。第一个赌注是考虑装饰图案:

Customer <<Interface>>     

|                       
CustomerImpl  



DiscountDecorator <<AbstractClass>> imp Customer

 |             |            |           |
AffiDiscount   StoreEmp   OverTwoYears   AnyOtherDisc
               Discount     Discount       Discount
Items  { 
//? ? :/
}
客户
|                       
客户模板
折扣装饰器imp客户
|             |            |           |
在任何其他光盘上粘贴折扣商店EMP超过两年
折扣
项目{
//? ? :/
}
但是
折扣
也取决于
项目

我有什么选择

  • 使用
    项目
    界面扩展
    客户
    界面以跟踪项目类型
  • 项目的
    列表
    传递给折扣类。 ... 如何正确地与
    客户
    项目
    类建立关系,以便我可以一起装饰它们

我认为您不应该使用decorator模式(除非我理解这个问题还有更多)。简单的多态性可以做到这一点

public abstract class AbstractCustomer implements Customer {

    private List<Item> items = new ArrayList<Item>();

    protected abstract double priceDiscountedPercentage(Item item);

    private double priceDiscounted(double bill) {
        return (bill - (Math.floor(bill / 100) * 5));
    }

    public void addItem(Item item) {
        items.add(item);
    }

    public double ringUp() {
        double bill = 0;
        for(Item item : items) {
            if(!item.isGrocery()) {
                bill += priceDiscountedPercentage(item);
            } else {
                bill += item.getPrice();
            }
        }
        return priceDiscounted(bill);
    }
}

我还不认为需要一种模式,也许可以这样做:

import java.util.EnumSet;
public class So35680415 {
    enum Discount {
        employee {
            @Override double discount(double amount) {
                return amount*.30;
            };
        },
        affiliate {
            @Override double discount(double amount) {
                // TODO Auto-generated method stub
                return amount*.10;
            };
        },
        customerForTwoYears {
            @Override double discount(double amount) {
                return Math.floor(amount/100)*100*.05;
            };
        };
        abstract double discount(double amount);
    }
    static class User {
        void discounts(double amount) {
            for(Discount discount:discounts)
                System.out.println("discount for: "+discount+" on: $"+amount+" is: $"+discount.discount(amount));
        }
        EnumSet<Discount> discounts=EnumSet.noneOf(Discount.class);
    }
    public static void main(String[] args) {
        User user=new User();
        user.discounts.add(Discount.employee);
        user.discounts(100);
        System.out.println("---");
        user.discounts.add(Discount.affiliate);
        user.discounts(100);
        System.out.println("---");
        user.discounts.add(Discount.customerForTwoYears);
        user.discounts(100);
        System.out.println("---");
    }
}
import java.util.EnumSet;
公共类So35680415{
枚举折扣{
雇员{
@覆盖双倍折扣(双倍金额){
退货金额*.30;
};
},
附属公司{
@覆盖双倍折扣(双倍金额){
//TODO自动生成的方法存根
退货金额*.10;
};
},
顾客两年{
@覆盖双倍折扣(双倍金额){
返回数学下限(金额/100)*100*.05;
};
};
双倍折扣(双倍金额);
}
静态类用户{
无效折扣(双倍金额){
对于(折扣:折扣)
System.out.println(“折扣:“+折扣+”在:$”+金额+“是:$”+折扣.折扣(金额));
}
EnumSet折扣=EnumSet.noneOf(折扣.class);
}
公共静态void main(字符串[]args){
用户=新用户();
用户.折扣.添加(折扣.员工);
用户折扣(100);
System.out.println(“--”);
用户.折扣.添加(折扣.附属);
用户折扣(100);
System.out.println(“--”);
user.discounts.add(Discount.customerfortwyears);
用户折扣(100);
System.out.println(“--”);
}
}

编辑以回答问题:它似乎没有违反srp,因为它只做了一件事,即计算折扣。枚举似乎非常适合此任务。枚举的类型是子类。添加另一个枚举很容易。它看起来确实有点像

@Downvoter请说明你的否决理由,这样问题就可以得到改进。为什么
Employee
类也必须实现
Customer
?它没有实现(至少在给出此示例的Java中没有实现),但如果接口继承不太麻烦的话,我喜欢对它进行明确的说明?2) 是否应为枚举分配此类任务?枚举中的类型不是有资格成为子类吗?如果将来会增加折扣呢?
import java.util.EnumSet;
public class So35680415 {
    enum Discount {
        employee {
            @Override double discount(double amount) {
                return amount*.30;
            };
        },
        affiliate {
            @Override double discount(double amount) {
                // TODO Auto-generated method stub
                return amount*.10;
            };
        },
        customerForTwoYears {
            @Override double discount(double amount) {
                return Math.floor(amount/100)*100*.05;
            };
        };
        abstract double discount(double amount);
    }
    static class User {
        void discounts(double amount) {
            for(Discount discount:discounts)
                System.out.println("discount for: "+discount+" on: $"+amount+" is: $"+discount.discount(amount));
        }
        EnumSet<Discount> discounts=EnumSet.noneOf(Discount.class);
    }
    public static void main(String[] args) {
        User user=new User();
        user.discounts.add(Discount.employee);
        user.discounts(100);
        System.out.println("---");
        user.discounts.add(Discount.affiliate);
        user.discounts(100);
        System.out.println("---");
        user.discounts.add(Discount.customerForTwoYears);
        user.discounts(100);
        System.out.println("---");
    }
}