This is the 14th day of my participation in the August More Text Challenge

Concept:

Classes change for one and only one reason: the principle that a class is responsible for one responsibility.

Program introduction:

If you define multiple responsibilities in a class at the beginning of your design, you should consider redesigning the class to break down its granularity into subclasses, each with a single responsibility.

Case Study:

Full code address: CodeSendBox

Requirement 1.0 explanation:

In the National Day approaching we want to carry out promotional feedback activities for high-quality customers, members of the user level 1 20% off for sale, members of the user level 2 30% off for sale.

Code implementation:

export class Product {
  // Different levels of members enjoy different discounts
  sell(member: number.discount: number) :void {
    if (member === 1) {
      console.log("National Day sales, honorable Level 1 members.");
      if (discount === 8) {
        console.log("Twenty percent off."); }}else if (member === 2) {
      console.log("National Day sales, honorable level 2 members.");
      if (discount === 7) {
        console.log("30% off."); }}}}Copy the code
// Two factors affect the product category;
import { Product } from "./v1";

new Product().sell(1.8);
new Product().sell(2.7);
Copy the code

Note: through the implementation of the above code, we can see that there are two variable factors when the commodity class is sold, one is the membership level, the other is to enjoy a discount.

Requirements Iteration 1.1 Explanation:

On the basis of the original, we also allow our users to use the coupons in their hands to discount activities, but different levels of membership also have different limits on the amount of coupons, the highest level of membership is 20 yuan, the highest level of membership is 50 yuan.

Code implementation:

export class Product {
  // On the basis of the original discount, members of different levels can enjoy different amount of coupon service
  sell(member: number.discount: number.coupons: number) :void {
    if (member === 1) {
      console.log("National Day sales, honorable Level 1 members.");
      if (discount === 8) {
        console.log("Twenty percent off.");
        if (coupons <= 20) {
          console.log("Use a coupon and subtract up to 20~"); }}}else if (member === 2) {
      console.log("National Day sales, honorable level 2 members.");
      if (discount === 7) {
        console.log("30% off.");
        if (coupons <= 50) {
          console.log("Use a coupon and subtract another 50~");
        }
      }
    }
  }
}
Copy the code
import { Product } from "./v2";

new Product().sell(1.8.20);
new Product().sell(2.7.50);
Copy the code

Function replay:

Through the first version of the code implementation and the second version of the iteration, we successfully sold the function to become larger, successive iterations, this method of complexity is impossible to calculate, every time it goes live will become a jumpy. In fact, the cause of the problem is the failure to consider future changes at the beginning of the design as a violation of the single responsibility.

Code refactoring:

Product category after redesign:
export class Product {
  service: IProductService;
  constructor(service: IProductService) {
    this.service = service;
  }

  sell() {
    this.service.member();
    this.service.discount();
    this.service.coupons(); }}Copy the code
Interface to define influencing factors of product sale:
interface IProductService {
  member(): void;
  discount(): void;
  coupons(): void;
}
Copy the code
The original product category is divided into two member customer categories according to the membership level:

Each level of customer separately maintains factors that are closely related to it

export class Level1Customer implements IProductService {
  member(): void {
    console.log("National Day sales, honorable Level 1 members.");
  }
  discount(): void {
    console.log("Twenty percent off.");
  }
  coupons(): void {
    console.log("Use a coupon and subtract up to 20~"); }}export class Level2Customer implements IProductService {
  member(): void {
    console.log("National Day sales, honorable level 2 members.");
  }
  discount(): void {
    console.log("30% off.");
  }
  coupons(): void {
    console.log("Use a coupon and subtract another 50~"); }}Copy the code
Client implementation:
import { Product, Level1Customer, Level2Customer } from "./v3";

new Product(new Level1Customer()).sell();
new Product(new Level2Customer()).sell();
Copy the code
Replay again:

After the reconstruction, the client side has the least amount of modification, and the split of product class leads to a sharp increase in code volume, but our class will become different from each other. When adding new conditions for selling solutions, the intrusion into the previous version will be less, and the extension will be simple and easy to maintain.