Skip to main content



Design Patterns (aka DP), Creational - Abstract Factory Pattern

DP is a well-described solution to a common software problem. Its benefits:

  • Already defined to solve a problem.
  • Increase code reusability and robustness.
  • Faster devlopment and new developers in team can understand it easily
DP defined in to 3 categories:
  • Creational - Used to construct objects such that they can be decoupled from their implementing system.
  • Structural - Used to form large object structures between many disparate objects
  • Behavioral - Used to manage algorithms, relationships, and responsibilities between objects.
To understand this please read factory pattern.

When you go through factory pattern:
  • You see that factory can produce only Computers or aptly varied types of Computers. But only Computers.
  • Now, Say you have a 3rd variety of Computer just like PC or Server. Say, Laptop class. You can easily inherit Computer an create your Laptops.
  • So, once you have Laptop. Thus your factory start delivering it automatically? No, that would require a bit modification to have place for Laptops.
  • That means, Laptop's are not automatically plugged-in to existing factory. Existing factory requires modifications to do so.
  • Now, If you modify existing Factory it would require testing, if it is working correctly.
  • Now, say earlier both PC and Server were manufactured by same Factory. But now PC is produced by different Factory and Server is produced by different.
  • What then!! Do client need to go to different factories for purchasing Computers?
If you get above bullets. Now as a consumer, I do not want to go to different factories neither as a producer, I want to modify my existing Factory.

Scenario:-
  • You have an interface or abstract class or normal class. Computer class.
  • For now you have only 1 implementation of Computer. That is, PC class.
  • Now, you need Factory for PC. But as you have seen above problems, you want your Factory to be designed in such a way that it does not require modification for a new Computer.
  • So, you create an abstract interface. ComputerAbstractFactory class.
  • Now you create a PC Factory inheriting ComputerAbstractFactory class.
  • Now, as a client I do not want to go to PC Factory. I want to go to only single Factory that produces Computers.
  • So, we create a class ComputerFactory that provides you Computers of any types provided client needs to tell them specific factories for item they need.
Uptil now Client is happy as it does not need to go to various factories. It just need to ask ComputerFactory to get him what he needs.
Producer is also happy as now he knows PC factory will only produce PC nothing else.
  • There is another kind of Computer in market. That is Server class.
  • And there is another company that created Server Factory to manufacture Servers.
With Abstract factory we do not need to worry to modify any of existing Factories. Client will just ask ComputerFactory to get him Servers from Server Factory.

package com.test.command.dp.creational.abstarctFactory;

public abstract class Computer {

       public abstract String getRAM();

       public abstract String getHDD();

       public abstract String getCPU();

       @Override
       public String toString() {

              return "RAM= " + this.getRAM() + ", HDD=" + this.getHDD() + ", CPU="
                           + this.getCPU();
       }

}

package com.test.command.dp.creational.abstarctFactory;

public class PC extends Computer {

       private String ram;
       private String hdd;
       private String cpu;

       public PC(String ram, String hdd, String cpu) {
              this.ram = ram;
              this.hdd = hdd;
              this.cpu = cpu;
       }

       @Override
       public String getRAM() {
              // TODO Auto-generated method stub
              return this.ram;
       }

       @Override
       public String getHDD() {
              // TODO Auto-generated method stub
              return this.hdd;
       }

       @Override
       public String getCPU() {
              // TODO Auto-generated method stub
              return this.cpu;
       }

}

package com.test.command.dp.creational.abstarctFactory;

public interface ComputerAbstractFactory {

       public Computer createComputer();
}

package com.test.command.dp.creational.abstarctFactory;

public class PCFactory implements ComputerAbstractFactory {

       private String ram;
       private String hdd;
       private String cpu;

       public PCFactory(String ram, String hdd, String cpu) {
              this.ram = ram;
              this.hdd = hdd;
              this.cpu = cpu;
       }

       @Override
       public Computer createComputer() {
              // TODO Auto-generated method stub
              return new PC(ram,hdd,cpu);
       }

}

package com.test.command.dp.creational.abstarctFactory;

public class ComputerFactory {

       public static Computer getComputer(ComputerAbstractFactory factory){
              return factory.createComputer();
       }
}

package com.test.command.dp.creational.abstarctFactory;

public class Server extends Computer {

       private String ram;
       private String hdd;
       private String cpu;
      
      

       public Server(String ram, String hdd, String cpu) {
             
              this.ram = ram;
              this.hdd = hdd;
              this.cpu = cpu;
       }

       @Override
       public String getRAM() {
              // TODO Auto-generated method stub
              return this.ram;
       }

       @Override
       public String getHDD() {
              // TODO Auto-generated method stub
              return this.hdd;
       }

       @Override
       public String getCPU() {
              // TODO Auto-generated method stub
              return this.cpu;
       }

}



package com.test.command.dp.creational.abstarctFactory;

public class ServerFactory implements ComputerAbstractFactory {

       private String ram;
       private String hdd;
       private String cpu;

       public ServerFactory(String ram, String hdd, String cpu) {
              this.ram = ram;
              this.hdd = hdd;
              this.cpu = cpu;
       }

       @Override
       public Computer createComputer() {
             
              return new Server(ram,hdd,cpu);
       }
      
      
}

package com.test.command.dp.creational.abstarctFactory;

public class TestDesignPatterns {

       /**
        * @param args
        */
       public static void main(String[] args) {
              testAbstractFactory();

       }

       private static void testAbstractFactory() {
              Computer pc = ComputerFactory.getComputer(new PCFactory(null, null, null));
              Computer server = ComputerFactory.getComputer(new ServerFactory(null, null, "2"));
             
              System.out.println("Dinesh Sachdev your PC is ready:"+pc);
              System.out.println("Dinesh Sachdev your Server is ready server);    
             
       }

}


Comments

Popular posts

Unix Server ( Edge Node ) hangs when there are many jobs running on hadoop cluster started from Unix Edge Node.

  When a unix server or an edge node is running lots of jobs (like Spark, Hadoop, or custom batch processes), crashes happen. For example. For example a process might hit a segementation fault, memory issue or ay other runtime issue. By default, if ulimit -c is not 0, the OS will create core dump. Core dump are written to disk and can be very large, sometimes hundreds of MBs or even GBs per process. What we realized was that when multiple processes crash at the same time, the system suddenly tries to write core files to disk. This was leading to DisK I/O spikes. Thus, node was becoming unresponsive. This was also leading CPU spike because OS was handling crash logging. Setting "ulimit -c 0" disables core dumps. This way we lose ability to debug crashes via core dump But, kept production edge nodes stable. On most Linux systems, by default, "core dumps" are written in current working directory of the process that crashes. Linux allows you to change core dump file nam...




VPN testing checklist

 To test: Is VPN active? Is it leaking? Does it look residential? Does it alter network fingerprints? Public IP Test (Basic Detection) - curl ipinfo.io DNS Leak Test - nslookup google.com MTU Test (Encapsulation Detection) - ping 8.8.8.8 -f -l 1472 TCP MSS Inspection - Use Wireshark and Look for SYN packets. Traceroute Path Test - tracert 8.8.8.8 WebRTC Leak Test - browserleaks.com/webrtc IPv6 Leak Test - test-ipv6.com Latency / Jitter Test - ping -n 50 8.8.8.8. VPN usually causes: More Jitters and Latency. Reverse DNS (PTR Record) - nslookup <your-public-ip> IP Reputation Check - Like most IP's from VPN Providers like Express VPN, etc. are blacklisted and all. Look for: Proxy/VPN classification, Hosting provider tagging




Spark-JDBC connection with Oracle Fails - java.sql.SQLSyntaxErrorException: ORA-00903: invalid table name

  While connecting Spark with Oracle JDBC, one may observe exception like below -  spark.read.format("jdbc"). option("url", "jdbc:oracle:thin:@//oraclehost:1521/servicename"). option("dbtable", "mytable"). option("user", "myuser").option("driver", "oracle.jdbc.driver.OracleDriver") option("password", "mypassword"). load().write.parquet("/data/out") java.sql.SQLSyntaxErrorException: ORA-00903: invalid table name at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951) at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513) at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227) at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208) ...




Agentic AI Development- Optimization- Bedrock Claude

Most of the models which you wish to invoke via AWS Bedrock, GPT, Google, etc, charges per token ( words/ characters ) For example -  A model like Claude is not a computer program that executes instructions. It is a statistical pattern matcher trained on text. It has no CPU, no memory, no ability to run code. It only predicts the next most likely token based on patterns it saw during training. But, some AI platforms give the model a sandboxed Python environment to actually execute code. Bedrock does have a Code Interpreter tool in Bedrock Agents — but that's a completely different setup- the overhead of setting it up just to decompress JSON makes zero sense when simply sending clean JSON is trivially easy. Easy Way To Estimate Your Cost- Step 1 — Measure your actual prompt size: Take your evidence JSON + instructions Paste into: https://platform.openai.com/tokenizer (OpenAI's tokenizer is close enough for estimation) It will tell you exact token count Step2 - Cost calculation C...




Spring MongoDB Rest API not returning response in 90 seconds which is leading to client timeout

  We have Spring Boot  Rest API deployed in Kubernetes cluster which integrates with MongoDB to fetch the data.  MongoDB is fed with data by a real time Spark & NiFi job.  Our clients complained that for a request what they send they don't have response within 90 seconds. Consider it like an OMS ( Order ManagEment System).  On further analysis, we found that Spark & NiFi processing is happenning within 10 seconds after consuming response data from Kafka. Thus, initally out thought was that it due to delay from upstream to produce data in to Kafka.  Thankfully, our data had create / request  timestamp, and when response was received, and when response was inserted into MongoDB. Subtracting response insert time from request time seemed to be well within 90 seconds. But, still client did timeout on not seeing a response within 90 seconds. This led to confusion on our side.  But, then we realized it was due to Read Preference . We updated this...