Which Design Pattern use

types of design patterns
design patterns c++
design patterns java
creational design patterns
design patterns gof
factory design pattern
singleton design pattern
structural design patterns

Let's say I have a class products where I have a stock and can pay in 2 ways: Paypal or cash. I can only sell 2 products cash. This might change in the future so I don't want to have to change the whole code with ifs and else so I thought of using the Strategy Pattern.

I'm just learning about design patterns. I'm most interesten in an UML design first before going to code.

So, is this a good pattern for my case? I might add more validations to the Cash class or to the Paypal class.

Edit: I add extra information.

It's just an example. I have only one validation, for example the maximum amount I can sell my products is $100 if it is cash or $10000 if it's Paypal. But let's say tomorrow they will ask me to add another validation that I cannot sell cash after 9pm. I don't know how to put it in the design no use the Strategy Pattern.

Edit2:

Let me put another example that might clarify.

You can make tickets reservation 2 ways: Paypal Or Cash. If you pay cash I want to allow only 2 tickets, but if you use Paypal you can buy whatever amount you want.

So I have a Class called Reservation that has 2 children: Paypal Cash

I have an integer that is called numberOfTickets on Reservation. On Cash I have a discount integer On paypal I have the account email.

Now I want to add some rules, the first one is to limit to 2 tickets if it is cash. Tomorrow I might have a 10 limit for Paypal.

So is the Strategy the best?

Your solution seems okay for now, however, I would rather suggest you make some sort of rules policy so that your reservation does not really care how it is paid, but rather that the rules are determined by the use case (you will notice that this solution is actually also technically based on the strategy pattern).

For example, let's say you have a Theatre class which is what you are booking tickets for. The following method is on this Theatre class:

public PaymentResult MakeReservation(IPaymentPolicy paymentPolicy, int itemsToBuy)
{
    var result = paymentPolicy.Verify(itemsToBuy);

    if(result.HasFailingRules)
    {
        return result;
    }

    // Do your booking here.
}

Here the theatre object is responsible for a single decision - is the reservation allowed given the rules provided to me? If yes then make the booking otherwise report the errors.

Then the caller has control over the rules based on the use case. For example:

public void MakePaypalReservation(int itemsToBuy)
{
    var rulesPolicy = new PaymentRulesPolicy(
                                              new MaxItemsRule(10),
                                              new MaxAmountRule(10000)
                                             );

    var theatre = this.repo.Load("Theatre A"); // Load by id

    var paymentResult = theatre.MakeReservation(rulesPolicy, itemsToBuy);

    // Here you can use the result for logging or return to the GUI or proceed with the next step if no errors are present.
}

public void MakeCashReservation(int itemsToBuy)
{
    var rulesPolicy = new PaymentRulesPolicy(
                                              new MaxItemsRule(2),
                                              new MaxAmountRule(100),
                                              new TimeOfDayRule(8, 20) //Can only buy between 8 in the morning at 8 at night as an example.
                                             );

    var theatre = this.repo.Load("Theatre A"); // Load by id

    var paymentResult = theatre.MakeReservation(rulesPolicy, itemsToBuy);

    // Here you can use the result for logging or return to the GUI or proceed with the next step if no errors are present.
}

Let's suppose that PaymentRulesPolicy has a constructor with this signature:

public PaymentRulesPolicy(params IRule[] rules);

You have a method per use case. If you can pay with some other method like a voucher, you can build a new policy with some new rules.

You will of course also have to provide the Theatre object with all the information it needs to make a booking. The rule policy's Verify() method will likely accept all of these pieces of information and pass the minimum required information to the individual rules.

Here is an example of what the rules policy might look like:

public class PaymentRulesPolicy
{
    private readonly IRule[] rules;

    public PaymentRulesPolicy(params IRule[] rules)
    {
        this.rules = rules;
    }

    public PaymentResult Verify(int numItemsToBuy, DateTime bookingDate)
    {
        var result = new PaymentResult();

        foreach(var rule in this.rules)
        {
            result.Append(rule.Verify(numItemsToBuy, bookingDate);
        }

        return result;
    }
}

This is already a bad interface since all rules require all information no matter what check it does. If this gets out of hand you could improve it by passing along the booking information when the policy is first constructed:

 var rulesPolicy = new PaymentRulesPolicy(
                                              new MaxItemsRule(2, itemsToBuy),
                                              new MaxAmountRule(100, itemsToBuy, costPerItem),
                                              new TimeOfDayRule(8, 20, currentDateTime) 
                                             );

At the end of the day the benefit of this pattern is that all your business decisions are encapsulated in one class each, which makes it extremely easy to maintain. Just looking at these policies' construction hopefully gave you a good overview of what they will enforce. You may then compose these rules into a larger policy.

The other benefit of this approach would also be unit testing. You could test rules very easily in isolation. You could even create a factory for the rules and test that the factory creates the correct policy with the correct rules for each use case, etc.

Remember that this is just one of many possible solutions and this particular solution might be overkill for your application or perhaps it does not fit well with the patterns you and your team are familiar with. As you experiment with your inheritance solution you might find that it is adequate or even simpler to understand given the habits and experience of your team.

Design Pattern - Overview, Design Patterns have become an object of some controversy in the programming world in recent times, largely due to their perceived 'over-use'  Software design patterns can and do lead to over-engineering. Over-engineering is the process of over complicating something. In the case of programming, making your code more complex and possibly more flexible than it needs to be. More specifically, implementing complex software design patterns on simple problems.

Your choice of using Strategy pattern is correct. To solve your expanding problem you can mingle with Decorator pattern as my sample code in Java below. To facilitate it I only used int type for all inputs like the amount, the time and the number of tickets.

Class Diagram

Implementation

public abstract class Payment {
protected int amount;
protected int time;
protected int numTickets;

public Payment (int amount, int numTickets) {
    this.amount = amount; 
    this.numTickets = numTickets;
}

public Payment (int amount, int time, int numTickets) {
    this.amount = amount; 
    this.time = time;
    this.numTickets = numTickets;
}

public abstract void doPayment();
}
public class CashPayment extends Payment {

public CashPayment(int amount, int time, int numTickets) {
    super(amount, time, numTickets);
}

@Override
public void doPayment() {
    System.out.println("Make the payment in Cash");
}
}

public abstract class Verificator {
protected Payment payment;
protected int maxAmount;
protected int maxTime;
protected int maxNumTickets;

public abstract void verify();
public abstract void verifyUpperBound(int amount, int max);
public abstract void verifyTime(int time, int max);
public abstract void verifyNumberTickets(int numTicket, int max);

public Verificator(Payment payment, int maxAmount, int maxNumTickets) {
    this.payment = payment;
    this.maxAmount = maxAmount;
    this.maxNumTickets = maxNumTickets;
}

public Verificator(Payment payment, int maxAmount, int maxTime, int 
maxNumTickets) {
    this.payment = payment;
    this.maxAmount = maxAmount;
    this.maxTime = maxTime;
    this.maxNumTickets = maxNumTickets;
}   
}

public class CashPaymentVerificator extends Verificator {

public CashPaymentVerificator(Payment payment, int maxAmount, int maxTime, int maxNumTickets) {
    super(payment, maxAmount, maxTime, maxNumTickets);
}

@Override
public void verify() {
    verifyUpperBound(this.payment.getAmount(), this.maxAmount);
    verifyTime(this.payment.getTime(), this.maxTime);
    verifyNumberTickets(this.payment.getNumTickets(), this.maxNumTickets);
}

@Override
public void verifyUpperBound(int amount, int max) {
    if (amount > max)
        throw new IllegalStateException("Can not pay cash over $"+max);
}

@Override
public void verifyTime(int time, int max) {
    if (time > max)
        throw new IllegalStateException("Can not pay cash after "+max+" PM");
}

@Override
public void verifyNumberTickets(int numTicket, int max) {
    if (numTicket > max)
        throw new IllegalStateException("Can not reserve more than "+max+" 
tickets by cash");
}
}

public class Context {
private Payment payment;

public Context(Payment payment) {
    this.payment = payment;
}

public void doPayment() {
    this.payment.doPayment();
}
}

public class StrategyMain {

public static void main(String[] args) {
    Payment payment = new CashPayment(99, 8, 1);
    Verificator verificator = new CashPaymentVerificator(payment, 100, 9,2);
    verificator.verify();

    Context context = new Context(payment);
    context.doPayment();

    payment = new PaypalPayment(1000, 11);
    verificator = new PaypalPaymentVerificator(payment, 10000, 10);
    verificator.verify();

    context = new Context(payment);
    context.doPayment();
}
}

The 3 Types of Design Patterns All Developers Should Know (with , Some of the popular design patterns: Design Patterns | Set 1 (Introduction) Design Patterns | Set 2 (Factory Method) Observer Pattern | Set 1 (Introduction) Observer Pattern | Set 2 (Implementation) Singleton Design Pattern. Decorator Pattern | Set 1 (Background) The Decorator Pattern | Set 2 (Introduction and Design) 8 design patterns that every developer should know Singleton. This is the most used pattern. A lot of framework already implement this pattern, Fluent Builder. Some objects require lots of parameters to be created. Finalizing Of course there are a lot of others useful design patterns,

First, consider the nature of the rule. Is it a general rule of cash that you can only accept cash for item 1 but not item 2? At my store I'll take cash for anything. Is it a rule that stores can only accept $100 in cash? Again, not at my store, where I'll take any amount of cash.

Now think about it from the GUI - after 9:00 PM, you might not even want to display the "cash" button, so the cashier knows cash is not allowed. You haven't even created a cash object yet - there's no way to execute the strategy in the cash object. That is a big clue that the cash object should not contain the strategy you're talking about.

So the limits here don't seem to be properties of cash at all, they seem to be business rules. These rules need to be applied before you even figure out what kind of tender they're paying with.

These might be rules on your transaction object. Your business is not allowing a single transaction to contain both Item 2 plus Cash tender. That seems plausible to me.

Or maybe these are business rules that apply outside of your domain objects of items, transactions, and tenders, and they need to exist in some kind of rules engine that validates items and tenders as they're added to the transaction.

There are a lot of ways to consider the problem. Instead of asking about design patterns, examine your objects in view of the SOLID design principles. If it seems like you're giving inappropriate responsibility to an object, you probably need to find a different place for the logic.

The 7 Most Important Software Design Patterns - educative, Creational design patterns are the Factory Method, Abstract Factory, Builder, Singleton, Object Pool, and Prototype. Use case of creational design pattern- 1)  A design pattern is the re-usable form of a solution to a design problem. The idea was introduced by the architect Christopher Alexander and has been adapted for various other disciplines, notably software engineering. 5 Further reading. 6 External links. An organized collection of design patterns that relate to a particular field is called a

Software design pattern, Design patterns provide a standard terminology and are specific to particular scenario. For example, a singleton design pattern signifies use of single object so​  Design patterns are used to represent some of the best practices adapted by experienced object-oriented software developers. A design pattern systematically names, motivates, and explains a general design that addresses a recurring design problem in object-oriented systems.

Software Design Patterns, Unfortunately there are a lot of developers who still refuse to use a few For sure two of the most useful design patterns, specially using them  In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. A design pattern isn't a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.

Design Patterns, Design patterns help eliminate redundant coding. Learn how to use the singleton pattern, factory pattern, and observer pattern using Java. But remember one-thing, design patterns are programming language independent strategies for solving the common object-oriented design problems. That means, a design pattern represents an idea, not a particular implementation. By using the design patterns you can make your code more flexible, reusable and maintainable.

Comments
  • What does it mean by "I can only sell 2 products cash?"
  • It's just an example. I have only one validation, for example the maximum amount I can sell my products is $100 if it is cash or $10000 if it's Paypal. But let's say tomorrow they will ask me to add another validation that I cannot sell cash after 9pm. I don't know how to put it in the design no use the Strategy Pattern.
  • The given information is not enough for me to tell you what design pattern to use.
  • Let me put another example that might clarify. You can make tickets reservation 2 ways: Paypal Or Cash. If you pay cash I want to allow only 2 tickets, but if you use Paypal you can buy whatever amount you want. So I have a Class called Reservation that has 2 children: 1: Paypal 2: Cash I have an integer that is called numberOfTickets on Reservation. On Cash I have a discount integer On paypal I have the account email. Now I want to add some rules, the first one is to limit to 2 tickets if it is cash. Tomorrow I might have a 10 limit for Paypal. So is the Strategy the best?
  • Strategy is appropriate, but not strategy methods contained in the Reservation class. Again, the strategy you are talking about is your business's rules about paying for reservations, but these are not the strategies of reservations.