当前位置:网站首页>Factory and strategy mode implementation scheme of coupons

Factory and strategy mode implementation scheme of coupons

2022-06-10 21:28:00 Wanglifeng

 

The most frequently used pattern in real development is basically 【 Strategy 】 and 【 factory 】 These two patterns .

according to " International practice " First introduce some concepts and examples of patterns .( The sample reference Head First, But try to be more concise and clear than it says )

After that, I will explain in detail the design and mode application of coupons .

 

All object-oriented beginnings are based on people 、 Animal as an example . Explain what is 【 Inherit 】 Etc . This is intuitive .

But in practice , Inheritance is limited in its use , It has its problems , It is a kind of 【 Strong coupling 】 The way , In general use 【 The strategy pattern 】【 Decoration mode 】 Instead of inheriting .

 

Take duck animal design as an example , Explain the problems with inheritance :

 

 

All ducks have quack and swim Ability , So superclasses implement these two functions .

display It's an abstract method , Each subclass duck is responsible for implementing its own display function .

This makes good use of the parent class inheritance function 【 Reuse 】 Characteristics of .

( Intuitive first thought , It is also a good case of object-oriented learning )

 

 

Some functions are well defined , Some functions are very “ embarrassed ”, for example fly function .

fly Cannot be added to a superclass , Because not all ducks have fly function .

If it is added to a superclass, it will cause all subclasses to implement or inherit this method that may not be applicable .

And not all ducks can quack( For example, the wooden toy duck ), Those don't have quack The duck of , Also implement or inherit quack.

There are some problems in using inheritance to achieve code reuse :

  1. alike display Function code is repeated in subclasses , The code doesn't have 【 Reuse 】.
  2. Of these subclasses of ducks display、fly The code is written dead , It's hard to change at runtime .
  3. Because each display Functions are scattered among different subclasses of ducks , It's hard to know all the behavior .
  4. We have modified the parent class, which will cause the whole body to be affected . All ducks are affected . At the same time, we modify a certain same type display When acting , Each duck needs to find the same code to modify .

 

Design to upgrade :

 

Through the form of interface , Give Way “ some ”( Not all ) Ducks can fly or cry .

Whoever needs it will implement the corresponding interface .

for example : You can fly and you will achieve flyable Interface , You can't fly , You just don't do anything .

 

Some problems are solved through the interface , Because not all subclasses of ducks have fly, and quack Behavior . There is no need to inherit or implement functions that do not apply to you .

But the code cannot 【 Reuse 】 The problem still exists .

We maintain in each subclass display,quack function , Probably many subclasses have the same function , Not reused , Modify the same behavior , Ask each class to find , Modify one by one .

At the same time, the code is scattered in each implementation class , Don't know all the actions .

 

 

Design ideas and principles :

The only commonality of software projects :【 Demand is constantly changing 】

So here's what we're going to do 【 Identify changes 】【 Isolate change 】, Every iteration or requirement change , The modification range is controllable , Between modules 【 loose coupling 】.

It's best not to touch the mature code that has been tested and production verified , Try to follow 【 Opening and closing principle 】.

There is a question whether to isolate 【 Single responsibility 】 Principle judgment , If two modules are modified for different reasons , Each other's modification does not necessarily involve the other's modification . Then they should be isolated .

Isolation means , They code in different ways 、 Or in different classes 、 Or in different service modules 、 Even in different systems .

Example , Of every duck fly and quack It will be different from duck to duck . We set up two groups of classes , A group and fly relevant , A group and quack relevant .

fly There are various classes fly How to implement . for example : Flying with wings is an implementation class . Flying with a rocket is another implementation class .

So for a kind of duck that uses wings to fly , I try to put the corresponding fly Class to it , And that's what happened fly Methodical 【 Reuse 】 and 【 centralized management 】

The next thing we need to solve is how to make this implementation class fly with wings “ Give to the ” This specific duck .

 

Insert a concept :

【 Programming to an interface 】

What is an interface ?

An interface is an agreed specification 、 password 、 Drawing .

like , People everywhere , I understand “ roll ” This language interface command , There are also corresponding implementations . Although everyone is different 、 Different ideas 、 Physical differences .

But I heard you tell him “ roll ”, Everyone will perform the action of stepping the leg , According to the race , In some places, people may beat you with their legs , In some places, people run on foot .

The different ways that different people react , We call it 【 polymorphic 】.

Although the language interface is the same , It's all one “ roll ” Voice input for . But the concrete implementation classes are different , The reaction is also different .

for example : There are many connectors on the computer motherboard , These interfaces are clearly defined , For example, voltage 、 sequential 、 Communication protocol 、 Functions, etc .

These are the norms . You follow this rule , You can get the result defined by the specification and return .

Different memory manufacturers have their own memory modules . Their memory chips 、 The board schemes are all different , But their slots are the same , They all implement the memory interface specification .

As long as the computer complies with the memory interface specification , Give the same instructions . Memory modules from any manufacturer can perform storage operations .

I used to hear a saying , The first-class company sets the standard , Second rate companies make products .

In fact, a specification is an interface , Large companies define the implementation scheme and the interfaces to be implemented by the scheme , Other companies implement these interfaces based on their own raw materials , This product will be launched .

 

So-called 【 To program for an interface , Don't program for implementation 】

You learn how to make a person roll , We must learn Mandarin , Because people in most places can understand , But the reaction is different .

If you study for a specific group of people , Then your skill is limited to a few people , For example, only people in Fujian can understand Minnan .

Another example , Your computer motherboard memory interface is developed exclusively for Samsung , Only Samsung knows the instructions , Other brands of memory modules can't even be plugged in .

Who would buy such a motherboard , Tied to Sanxing , He said you would have to pay for the price increase . Otherwise the whole computer won't work .

Board for interface implementation . I can exchange cheap domestic memory with the same interface . Or that sentence “ It's not useless , Long live Sister Li ”.

 

Explain the concept , Let's look at how programming applies .

Let's take one person's one-day activities as an example .

class PersonDayAct{
     DayAct act = new  Code the agriculture ();
     act.dayAct();
     act.nightAct();                   
}
act.dayAct();
act.nightAct();
The interface methods we all use , Are using interfaces in programming . The advantage is that if we want to print the rich second generation one day .

DayAct act = new Rich second generation (); Just modify this line of code .
 Through polymorphism , We can print the one-day activities of the rich second generation .
And this new operation , We can replace it with a later factory model . If you want to print other people's Day activities later .
We just need to create a new implementation class . There is no need to change the previously written and tested code . accord with 【 Opening and closing principle 】


Finished 【 Interface oriented programming 】, Let's continue with the duck example .
The alternative to inheritance is 【 Combine 】, Multipurpose combination , Use less inheritance .
“ There is one ” Than “ It's a ” Better , Every duck has a FlyBehavior And a QuackBehavior, So that they can handle the flight and cooing .
Duck behavior is not inherited , But and “ appropriate ” The object of “ Combine ” And come .
The benefits of combination :

1. Encapsulate a class of behavior into a class
2. Dynamically changing behavior at runtime .

 

public abstract class Duck{

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    
    public Duck(){
    }
    
    public abstract void dispaly();
    
    public void performQuack(){
        quackBehavior.quack();
    }
    
    public void performFly(){
        flyBehavior.fly();
    }
    
    public void swim(){
        System.out.println("all ducks float,even decoys");
    }
}
Duck
public class Bduck extends Duck{

    public Bduck(){
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    public void setFlyBehavior( FlyBehavior fb){
        flyBehavior = fb;
    }
    
    public void setQuackBehavior( QuackBehavior qb){
        quackBehavior = qb;
    }
    
    public void display(){
        System.out.println("i am Bduck");
    }
    
}
Bduck
public class Test{

    public static void main(String[] args){
        Duck d = new Bduck();
        d.performFly();
        d.setFlyBehavior(new FlyRocketPowered());
        d.performFly();
    }
}
Test

 

summary :

The strategy pattern : Define algorithm family , Separately encapsulated , So that they can replace each other , This pattern makes the algorithm change independent of the customer using the algorithm .

explain : In the example, the duck's flight has different strategies , Some fly with their wings , Some fly by rocket .

Different people treat “ roll ” This directive also has its own different coping strategies , Some are running , Some come forward and beat you .

And these strategies can 【 Reuse 】 and 【 Unified management 】 Of . We go through 【 Combine 】 The way , The strategy “ Put in ” Go to class , Different policies can be changed at runtime .

Instead of inheriting to get this behavior . Composition is more flexible than inheritance , And convenient .

 

But the strategic model also leaves a problem , how “ Put in ” This policy object into the class , If it is new Object form , This is like new The policy binding of is dead .

What we want is , While the program is running , Through different input parameters , Dynamically combine different implementation classes . To achieve different behaviors .

for example : We get different coupon implementation classes through the coupon type field . Some are full minus , There are discounts , But the program doesn't care about these types .

He only needs to entrust the price calculation to different strategies to calculate the final price .

 

Simple factory model :

The responsibility of the factory is to build new products .

The following single pizza is an example .pizza Interface defined pizza Production method of . Different kinds of pizza Responsible for their own implementation , Different pizza Some bake for a long time , Some cut small pieces .

The following is typical interface oriented programming , There's even a bit of a strategic pattern .

 


 
Pizza orderPizza(String type){
    
    Pizza pizza;
    
    if(type.equals("cheese")){
        pizza = new CheesePizza();
    }else if(type.equals("greek")){
        pizza = new GreekPizza();
    }else if(type.equals("pepperoni")){
        pizza = new PepperoniPizza();
    }
    
    pizza.prepare();
    pizza.babke();
    pizza.cut();
    pizza.box();
    return pizza;
}

The only problem is , If I pizza The categories of have been added and deleted , I need to modify if-else This code . This violates 【 Opening and closing principle 】

We should change the place 【 Isolate change 】.

 

Simple factory :

public class PizzaStore{

    SimplePizzaFactory factory;
    
    public PizzaStore(SimplePizzaFactory factory){
        this.factory = factory;
    }
    
    Pizza orderPizza(String type){
        Pizza pizza = factory.createPizza(type);
        
        pizza.prepare();
        pizza.babke();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

 

public class SimplePizzaFactory{
    public Pizza createPizza(String type){
        Pizza pizza;
    
        if(type.equals("cheese")){
            pizza = new CheesePizza();
        }else if(type.equals("greek")){
            pizza = new GreekPizza();
        }else if(type.equals("pepperoni")){
            pizza = new PepperoniPizza();
        }
        
        return pizza;
    }
}


simplePizzaFactory Just do one thing , New pizza .

For those requiring singleton, we can use the singleton mode :

1. Hungry Han style of singleton mode [ You can use ]
public class Singleton {
 
    private static Singleton instance=new Singleton();
    private Singleton(){};
    public static Singleton getInstance(){
        return instance;
    }
}
 access 

Singleton instance = Singleton.getInstance();

2. Singleton mode lazy double check lock [ Recommend to use ]
class Singleton{
    private volatile static Singleton instance = null;

    private Singleton() {
         
    }
    public static Singleton getInstance() {
        if(instance==null) {
            synchronized (Singleton.class) {
                if(instance==null)
                    instance new Singleton();
            }
        }
        return instance;
    }
}
 access 

Singleton instance = Singleton.getInstance();

3. Inner class [ Recommend to use ]

public class Singleton{
 
    
    private Singleton() {};
    
    private static class SingletonHolder{
        private static Singleton instance=new Singleton();
    } 
    
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}

 access 

Singleton instance = Singleton.getInstance();

 When instantiation is required , call getInstance Method , Will be loaded SingletonHolder class , To complete the Singleton Instantiation .

4. Enumeration form 
public enum Singleton {

    INSTANCE;

    public void doSomething() {
        System.out.println("doSomething");
    }

}
 Calling method :

public class Main {

    public static void main(String[] args) {
        Singleton.INSTANCE.doSomething();
    }

}

 Directly through Singleton.INSTANCE.doSomething() Call in the same way . convenient 、 Simple and safe .

 An example of lazy style 
Singleton implementation mode

The benefits of factory packaging :

  1. Many places may need new construction pizza object . If there is pizza Add, delete or change the category , We just need to modify it simplePizzaFactory This is a place .【 Avoid multiple modifications 】,
    Sometimes creating new objects is not as simple as a line of code , Such as connection pool , Centralized management is important .
  2. createPizza The way can be static Of . The advantage is that you don't need to instantiate an object to use , The disadvantage is that you can't change the behavior of creating methods through inheritance .
  3. The factory mode enables us to realize 【 Dependency inversion 】, Although it has been oriented to interface programming before , But we must always new Specify the concrete implementation class , once new Specific implementation classes are given ,
    Although it is interface oriented programming , But it is equivalent to binding with the concrete implementation , Cannot be changed at runtime .
    With the factory , Our high-level components now only rely on interfaces or abstract classes , The underlying implementation classes are also dependent on interfaces or abstract classes . Does not depend on concrete implementation classes . The concrete implementation classes can be dynamically generated by the factory by passing parameters at runtime .

Disadvantages of factory packaging :

  1. If there is pizza Add, delete or change the category , Although only one change is needed , Many modifications are avoided . But we still need to modify the simple factory if-else, There is still a violation 【 Opening and closing principle 】.

 

In order to observe 【 Opening and closing principle 】, There are two ways : Upgrade simple factory 、 Factory method model .

Upgrade simple factory :

A factory can also be an interface or an abstract class , Our factory may also have many implementation methods .

We first implemented a AStyleSimplePizzaFactory, If subsequent requirements change ,pizza Categories have been added , We can create a new BStyleSimplePizzaFactory.

You can think of it as a sort of classification . For example in China , Bean curd manufacturers . Both the South and the North produce bean curd , But a sweet mouth and a salty mouth .

 

pizza Stores can be classified according to flavor :

 

 

Vehicles can also be classified by type :

In fact, you can not follow this classification .
It's a simple factory , Inside through if-else Judge , Build different flavors pizza Also no problem .
Again , You can also take the vehicle out of accordance with “ Land, sea and air ” Way classification .
I am in a simple factory , Return instances of different types of vehicles . No problem at all .

but, however ....
Follow the project progress , We can't predict how much demand will be added later , We can only write a version according to the known ,
Really add products or logic in the future , We don't change the previous code . We can only create new processing plants and implementation classes .
Just to conform to 【 Opening and closing principle 】

You can think that the first phase only has AStyleSimplePizzaFactory, As the project iterations , Various B、C The factories are all coming out .

Personally think :
Most projects don't have to use such a complex and simple factory at first ,【 Simple software has simple software design 】,
Subsequent iterations to modify the factory class , Or it is the right way to slowly evolve to this upgraded simple factory after there is demand .

Old mages are all thinking about simplicity and efficiency , Novices want to be high-level and strong .

public interface Moveable {
    void run();
}

public class Car implements Moveable{
    @Override
    public void run() {
        System.out.println("driving.....");
    }
}

public class Plane implements Moveable{
@Override
    public void run() {
        System.out.println("flying...");
    }
}
// Vehicle factory 
public abstract class VehicleFactory {
// The specific vehicle generated is determined by the subclass , This is abstract .
    public abstract Moveable create();
}

//Car Factory 
public class CarFactory extends VehicleFactory{
    
    @Override
    public Moveable create() {
        // Single case 、 Multiple cases 、 Condition check self control 
        return new Car();
    }
}
// Aircraft factory 
public class PlaneFactory extends VehicleFactory {
    
    @Override
    public Moveable create() {
        // Single case 、 Multiple cases 、 Condition check self control 
        return new Plane();
    }
}

public class Test{
    public static void main(String[] args){

        VehicleFactory factory = new PlaneFactory();
    Moveable m = factory.create();
    m.run();

    // Switch to Car factory 
    factory = new CarFactory();
    m = factory.create();
    m.run();

    }    
}

 Vehicle factory 
Vehicle factory

 

Factory method model :

 

 

public abstract class PizzaStore{
    
    public Pizza orderPizza(String type){
        Pizza pizza;
        
        pizza = createPizza(type);
        
        pizza.prepare();
        pziza.bake();
        pizza.cut();
        pizza.box();
        
        return pizza;
    }
    
    abstract Pizza createPizza(String type);
}

public class AStylePizzaStore extends PizzaStore{
     public Pizza createPizza(String type){
        if(type.equals("chesse")){
            pizza = new AStyleChessePizza();
        }else if(type.equals("peperoni")){
            pizza = new AStylePepperoniPizza();
        }
    }
}


When called, i.e :

PizzaStore  store = new AStylePizzaStore();
store.orderPizza("cheese");
 

 

 

Factory method model :
Define an interface for creating objects , But the subclass decides which class to instantiate .
Factory methods let classes defer instantiation to subclasses .

 

  Examples of factory methods :

 

 

 

 

The benefits of the factory approach :

1. Solidify many methods and processes in the parent class , It is conducive to standardized operation , Implement and use the product 【 decoupling 】.

2. When we add new products , Or when the product has other styles and implementations , We can according to 【 Opening and closing principle 】, Add new subclasses .

3. Factory methods may not be abstract , It is equivalent to giving a default implementation method .

Disadvantages of factory methods :

1. As the business grows , There may be more and more subclasses , Difficult to manage ( There is abstract factory management ).

2. Whether it's a simple factory upgrade , Or factory method . Most of the time, we do not upgrade in black or white , It is as simple as replacing the old factory with the new one , Or the new factory will take charge of the old factory , But two factories exist at the same time .

for example : I used to make sweet tofu flowers , Now I have to make salted bean flowers , But the main business logic does not move . If you add a new subclass .
How can we dynamically specify factories ? Are you building a factory ? Suddenly I feel like a simple factory YYDS 了 .

In fact, we still have to distinguish , This new product adds , The original business logic remains unchanged , The original business logic code needs to be changed .

If the original main logic code does not move , We should need to modify if-else Of , Because the essence is that the parameters are increased .

If it is extended , We should create new subclasses , Then expand the newly added code and use the newly added subclasses .

 

 

As for when to use interfaces , When to use abstract classes :

If this concept really exists in our minds , Just use abstract classes . Or you have reusable methods that you want subclass inheritance to use directly .
If this concept is only a feature of certain aspects : Like flying , Will run , Just use the interface
If two concepts are vague , When I don't know which one to choose , Just use the interface , as a result of java It's single inheritance , Multi interface implementation , This inheritance is valuable , After implementing this interface , You can also inherit from other abstract classes , More flexible .

 

  Abstract factory :

To control the number of factory subclasses . It is not necessary to assign a factory class to each product . You can group products , Different products in each group have different methods of the same factory class to create .

  This is very similar to the upgraded version of a simple factory . But note that an abstract factory is a factory that generates different things . It is produced according to series .

We are equipped with American equipment , It contains a pistol 、 Cannon and a series of .

We are equipped with German equipment , Inside is another set of pistols 、 artillery 、 Automobile, etc .

 

 

 

// The traffic tools 
public abstract class Vehicle {
    // Implementation is determined by subclasses 
    public abstract void run();
}
// food 
public abstract class Food {
    public abstract void printName();
}
// weapons 
public abstract class Weapon {
    //
    public abstract void shoot();
}
Product interface
// Abstract factory 
public abstract class AbstractFactory {
    // production   The traffic tools 
    public abstract Vehicle createVehicle();
    // production   weapons 
    public abstract Weapon createWeapon();
    // Produce food 
    public abstract Food createFood();
}

// Harry Potter's magic factory 
public class MagicFactory extends AbstractFactory {
// The traffic tools : Broom 
    public Vehicle createVehicle(){
        return new Broom();
    }
    
    // weapons : Magic wand 
    public Weapon createWeapon(){
        return new MagicStick();
    }
    // food : Poisonous mushroom 
    public Food createFood(){
        return new MushRoom();
    }
}

// Default factory 
public class DefaultFactory extends AbstractFactory{
@Override
    public Food createFood() {
        return new Apple();
    }
@Override
    public Vehicle createVehicle() {
        return new Car();
    }
@Override
    public Weapon createWeapon() {
        return new AK47();
    }
}
factory
public class Car extends Vehicle{
    @Override
    public void run() {
        System.out.println(" Running in smoke ...");
    }
}
// A broom 
public class Broom extends Vehicle{
@Override
    public void run() {
        System.out.println(" The broom wagged its tail ...");
    }
}
// food : Poisonous mushroom 
public class MushRoom extends Food {
@Override
    public void printName() {
        System.out.println("mushroom");
    }
}
public class Apple extends Food {
    @Override
    public void printName() {
        System.out.println("apple");
    }
}
public class AK47 extends Weapon{
public void shoot(){
        System.out.println(" dadada ....");
    }
}
// weapons : Magic wand 
public class MagicStick extends Weapon {
    @Override
    public void shoot() {
        System.out.println("fire hu hu hu ...");
    }
}
product
// Change a factory , Just change this one , That's all right. , Change a factory , Just replace the series of products produced 
        AbstractFactory factory =  new DefaultFactory(); //new DefaultFactory();
        // Change a factory 
        Vehicle vehicle = factory.createVehicle();
        vehicle.run();
        Weapon weapon = factory.createWeapon();
        weapon.shoot();
        Food food = factory.createFood();
        food.printName();
test

Abstract factory class diagram :

 

 

 

  Abstract factories allow customers to create a set of related products using abstract interfaces , You don't need to care about what the actual output is .

In this way, customers can learn from specific products 【 decoupling 】

  Abstract factory createProductA This method looks like a factory method . Parent class definition , Subclass implementation .

 

summary :

Simple factory : The only factory class , A product abstract class , The creation method of factory class judges and creates specific product objects based on input parameters .

Factory method : Multiple factory classes , A product abstract class , Use polymorphism to create different product objects , Avoid a lot of if-else Judge .

Abstract factory : Multiple factory classes , Multiple product abstract classes , Product subclass grouping , The same factory implementation class creates different products in the same group , Reduce the number of factory subclasses .

 

 

Examples of practical applications :

The scope of strategy and factory application is too frequent , No special examples .

Take coupons, for example .

 

  Coupons are divided into types : Full discount 、 coupon 、 wait . These types of vouchers determine how to write off when calculating the price . This is a strategy . It's the same as how different ducks fly .

The same coupons also apply . Which commodities are suitable for 、 store 、 wait .

There are a lot of coupons , This launch may be shared in many channels and activities . for example :A The coupons will be put 100 Zhang , In the home page Activity Center 、 Offline code scanning and receiving at the same time . Until I've received it .

 

Ideas :

Coupons are the most important : Discount method and calculation 、 Term of validity method and calculation 、 Scope of application and calculation .

Take discount as a strategy . Combined into the properties of the coupon . It's like a duck combining a flying strategy .

Similarly, the validity period of the coupon is calculated , Some are effective immediately , Some take effect at a fixed time .

Currently, only the default method is available for the application scope of the coupon .

Through simple parameter chemical plant :

Pass ticket type code To get examples of different discount strategies ,

Pass ticket validity_type Get policy instances with different validity periods .

Scope of application , Currently, there is only the default calculation method . Chemical plant without parameters .

 

 

 

The atmosphere is all here , By the way, let's talk about the remaining two creation modes : Archetypal model 、 Builder pattern .

Archetypal model :

 

 

public abstract class Shape implements Cloneable {
   
   private String id;
   protected String type;
   
   abstract void draw();
   
   public String getType(){
      return type;
   }
   
   public String getId() {
      return id;
   }
   
   public void setId(String id) {
      this.id = id;
   }
   
   public Object clone() {
      Object clone = null;
      try {
         //  Shallow copy     
         clone = super.clone();
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
      return clone;
   }
}
Shape
public class Rectangle extends Shape {
 
   public Rectangle(){
     type = "Rectangle";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square extends Shape {
 
   public Square(){
     type = "Square";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle extends Shape {
 
   public Circle(){
     type = "Circle";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}
ConcreteShape
public class ShapeCache {
    
   private static Hashtable<String, Shape> shapeMap 
      = new Hashtable<String, Shape>();
 
   public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.clone();
   }
 
   //  Run database queries for each shape , And create the shape 
   // shapeMap.put(shapeKey, shape);
   //  for example , We're going to add three shapes 
   public static void loadCache() {
      Circle circle = new Circle();
      circle.setId("1");
      shapeMap.put(circle.getId(),circle);
 
      Square square = new Square();
      square.setId("2");
      shapeMap.put(square.getId(),square);
 
      Rectangle rectangle = new Rectangle();
      rectangle.setId("3");
      shapeMap.put(rectangle.getId(),rectangle);
   }
}
ShapeCache
public class PrototypePatternDemo {
   public static void main(String[] args) {
      ShapeCache.loadCache();
 
      Shape clonedShape = (Shape) ShapeCache.getShape("1");
      System.out.println("Shape : " + clonedShape.getType());        
 
      Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
      System.out.println("Shape : " + clonedShape2.getType());        
 
      Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
      System.out.println("Shape : " + clonedShape3.getType());        
   }
}
Test

 


  Archetypal model , seeing the name of a thing one thinks of its function , Give you a prototype , You can get a lot of the same or similar objects according to the prototype , This is done by cloning the object .

For high net worth , Creating objects with extremely complex processes , You can use this model to build a lot of , There is no need to new, That's too inefficient .

(1) Shallow clone

In shallow cloning , If the member quantity of the prototype object is 8 Big basic data types (byte、short、int、long、float、double、char、boolean、 In addition to this 8 Kind of , All are reference types , especially String At the bottom is the character array , Not a basic data type ) A copy will be copied to the target , If the member variable of the prototype object is a reference type ( Such as class 、 Interface 、 Array and other complex data types ), Then copy a copy of the address of the reference object to the derogation object , in other words , The member variables of the prototype object and the clone object point to the same memory address . Simply speaking , In shallow cloning , When the prototype object is copied , Only copy itself and the member variables of the value type contained in it , The member variables of the reference type are not copied .

Example :

org.springframework.beans.BeanUtils.copyProperties(source,target);

(2) A deep clone

In shenklong , Whether the member variable of prototype object is value type or reference type , All will be copied to the cloned object , Deep clone copies all reference objects of the prototype object to the cloned object . Simply speaking , In shenklong , Except that the object itself is copied , All member variables contained in the object will also be copied .

Example :
org.apache.commons.lang3.SerializationUtils.clone(source);

 

 

Builder pattern :

 

 

class Product {
    private String partA;
    private String partB;
    private String partC;

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }

    public void show() {
        // Show product features 
    }
}
Product
abstract class Builder {
    // Create a product object 
    protected Product product = new Product();

    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    // Return product object 
    public Product getResult() {
        return product;
    }
}
Builder
public class ConcreteBuilder extends Builder {
    public void buildPartA() {
        product.setPartA(" build  PartA");
    }
    public void buildPartB() {
        product.setPartB(" build  PartB");
    }
    public void buildPartC() {
        product.setPartC(" build  PartC");
    }
}
ConcreteBuilder
class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    // Product construction and assembly methods 
    public Product construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}
Director
public class Client {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        Product product = director.construct();
        product.show();
    }
}
Client

 

Builder pattern , It mainly aims at the complex construction process of the object , Generally, it is composed of many sub components according to certain steps . The components of the product are unchanged , But each part is flexible .

for example : When we save computers , Tell the assembly shop about the requirements of various parts , The computer is made up of those , But hard drives ,cpu There can be many kinds of , He helped us assemble the computer ( And then they got stuck ....)

 

This article is from the blog Garden , author :wanglifeng, Reprint please indicate the original link :https://www.cnblogs.com/wanglifeng717/p/16339222.html

 

原网站

版权声明
本文为[Wanglifeng]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/161/202206101730109934.html