Overview of Design Patterns, SOLID Principles, and Java Implementations
This article introduces the three major categories of design patterns, explains the six SOLID principles, and provides detailed Java code examples for creational patterns such as Factory Method, Abstract Factory, Singleton, Builder, and Prototype, illustrating their structure and usage.
Design patterns are divided into three major categories: Creational (5 patterns: Factory Method, Abstract Factory, Singleton, Builder, Prototype), Structural (7 patterns: Adapter, Decorator, Proxy, Facade, Bridge, Composite, Flyweight), and Behavioral (11 patterns: Strategy, Template Method, Observer, Iterator, Chain of Responsibility, Command, Memento, State, Visitor, Mediator, Interpreter).
The six SOLID principles guiding good software design are: Open‑Closed Principle, Liskov Substitution Principle, Dependency Inversion Principle, Interface Segregation Principle, Law of Demeter (Least Knowledge), and Composite Reuse Principle.
Creational patterns are demonstrated with Java code examples. The Factory Method pattern includes ordinary, multiple, and static factory methods. Example interfaces and classes:
package com.mode.create;
public interface MyInterface {
public void print();
} package com.mode.create;
public class MyClassOne implements MyInterface {
@Override
public void print() {
System.out.println("MyClassOne");
}
} package com.mode.create;
public class MyClassTwo implements MyInterface {
@Override
public void print() {
System.out.println("MyClassTwo");
}
} package com.mode.create;
public class MyFactory {
public MyInterface produce(String type) {
if ("One".equals(type)) {
return new MyClassOne();
} else if ("Two".equals(type)) {
return new MyClassTwo();
} else {
System.out.println("没有要找的类型");
return null;
}
}
} package com.mode.create;
public class FactoryTest {
public static void main(String[] args) {
MyFactory factory = new MyFactory();
MyInterface myi = factory.produce("One");
myi.print();
}
}The multiple‑factory‑method variant adds separate methods for each product:
package com.mode.create;
public class MyFactory {
public MyInterface produceOne() {
return new MyClassOne();
}
public MyInterface produceTwo() {
return new MyClassTwo();
}
} package com.mode.create;
public class FactoryTest {
public static void main(String[] args) {
MyFactory factory = new MyFactory();
MyInterface myi = factory.produceOne();
myi.print();
}
}The static‑factory‑method version makes these methods static, eliminating the need to instantiate the factory:
package com.mode.create;
public class MyFactory {
public static MyInterface produceOne() {
return new MyClassOne();
}
public static MyInterface produceTwo() {
return new MyClassTwo();
}
} package com.mode.create;
public class FactoryTest {
public static void main(String[] args) {
MyInterface myi = MyFactory.produceOne();
myi.print();
}
}The Abstract Factory pattern introduces a Provider interface and separate factory classes to avoid modifying existing factories when extending functionality:
package com.mode.create;
public interface Provider {
public MyInterface produce();
} package com.mode.create;
public class MyFactoryOne implements Provider {
@Override
public MyInterface produce() {
return new MyClassOne();
}
} package com.mode.create;
public class MyFactoryTwo implements Provider {
@Override
public MyInterface produce() {
return new MyClassTwo();
}
} package com.mode.create;
public class FactoryTest {
public static void main(String[] args) {
Provider provider = new MyFactoryOne();
MyInterface myi = provider.produce();
myi.print();
}
}The Singleton pattern is shown with a lazy‑initialized instance holder:
package test;
public class MyObject {
private static MyObject myObject;
private MyObject() {}
public static MyObject getInstance() {
if (myObject != null) {
} else {
myObject = new MyObject();
}
return myObject;
}
}The Builder pattern separates construction of a complex object (Person) from its representation, using PersonBuilder, concrete builders (ManBuilder), a Director (PersonDirector), and a test class:
package com.mode.create;
public class Person {
private String head;
private String body;
private String foot;
// getters and setters omitted for brevity
} package com.mode.create;
public interface PersonBuilder {
void buildHead();
void buildBody();
void buildFoot();
Person buildPerson();
} package com.mode.create;
public class ManBuilder implements PersonBuilder {
Person person = new Person();
public void buildHead() { person.setHead("建造男人的头"); }
public void buildBody() { person.setBody("建造男人的身体"); }
public void buildFoot() { person.setFoot("建造男人的脚"); }
public Person buildPerson() { return person; }
} package com.mode.create;
public class PersonDirector {
public Person constructPerson(PersonBuilder pb) {
pb.buildHead();
pb.buildBody();
pb.buildFoot();
return pb.buildPerson();
}
} package com.mode.create;
public class Test {
public static void main(String[] args) {
PersonDirector pd = new PersonDirector();
Person person = pd.constructPerson(new ManBuilder());
System.out.println(person.getBody());
System.out.println(person.getFoot());
System.out.println(person.getHead());
}
}The Prototype pattern demonstrates shallow and deep cloning, with a class implementing Cloneable and Serializable, and utility methods for deep cloning via serialization:
package com.mode.create;
import java.io.*;
public class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private int base;
private Integer obj;
public Object clone() throws CloneNotSupportedException { return super.clone(); }
public Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
// getters and setters omitted
} package com.mode.create;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
Prototype prototype = new Prototype();
prototype.setBase(1);
prototype.setObj(new Integer(2));
Prototype prototype1 = (Prototype) prototype.clone(); // shallow copy
Prototype prototype2 = (Prototype) prototype.deepClone(); // deep copy
System.out.println(prototype1.getObj() == prototype1.getObj());
System.out.println(prototype1.getObj() == prototype2.getObj());
}
}Overall, the article reviews design pattern classifications, SOLID principles, and provides concrete Java implementations to help readers understand and apply these patterns in software development.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.