Skip to content

Commit 32cc03c

Browse files
author
turingfly
committed
Design Patterns and Principles
1 parent cac527e commit 32cc03c

7 files changed

+357
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package designPatternsAndPrinciples;
2+
3+
import java.util.List;
4+
import java.util.Arrays;
5+
6+
/**
7+
*
8+
* @author chengfeili
9+
* Jun 5, 2017 10:06:52 PM
10+
*
11+
* The builder pattern is a creational pattern in which parameters are
12+
* passed to a builder object, often through method chaining, and an
13+
* object is generated with a final build call.It is often used with
14+
* immutable objects, since immutable objects do not have setter methods
15+
* and must be created with all of their parameters set, although it can
16+
* be used with mutable objects as well.
17+
*/
18+
public class BuilderPattern {
19+
private String species;
20+
private int age;
21+
private List<String> favoriteFoods;
22+
23+
public BuilderPattern setAge(int age) {
24+
this.age = age;
25+
return this;
26+
}
27+
28+
public BuilderPattern setSpecies(String species) {
29+
this.species = species;
30+
return this;
31+
}
32+
33+
public BuilderPattern setFavoriteFoods(List<String> favoriteFoods) {
34+
this.favoriteFoods = favoriteFoods;
35+
return this;
36+
}
37+
38+
public Animal build() {
39+
return new Animal(species, age, favoriteFoods);
40+
}
41+
}
42+
43+
class BuilderPatternTest {
44+
Animal flamingo = new BuilderPattern().setFavoriteFoods(Arrays.asList("algae", "insects")).setSpecies("flamingo")
45+
.build();
46+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package designPatternsAndPrinciples;
2+
3+
/**
4+
*
5+
* @author chengfeili
6+
* Jun 5, 2017 10:21:53 PM
7+
*
8+
* The factory pattern, sometimes referred to as the factory method
9+
* pattern, is a creational pattern based on the idea of using a factory
10+
* class to produce instances of objects based on a set of input
11+
* parameters. It is similar to the builder pattern, although it is
12+
* focused on supporting class polymorphism.
13+
*/
14+
15+
abstract class Food {
16+
private int quantity;
17+
18+
public Food(int quantity) {
19+
this.quantity = quantity;
20+
}
21+
22+
public int getQuantity() {
23+
return quantity;
24+
}
25+
26+
public abstract void consumed();
27+
}
28+
29+
class Hay extends Food {
30+
public Hay(int quantity) {
31+
super(quantity);
32+
}
33+
34+
public void consumed() {
35+
System.out.println("Hay eaten: " + getQuantity());
36+
}
37+
}
38+
39+
class Pellets extends Food {
40+
public Pellets(int quantity) {
41+
super(quantity);
42+
}
43+
44+
public void consumed() {
45+
System.out.println("Pellets eaten: " + getQuantity());
46+
}
47+
}
48+
49+
class Fish extends Food {
50+
public Fish(int quantity) {
51+
super(quantity);
52+
}
53+
54+
public void consumed() {
55+
System.out.println("Fish eaten: " + getQuantity());
56+
}
57+
}
58+
59+
public class FactoryPattern {
60+
public static Food getFood(String animalName) {
61+
switch (animalName) {
62+
case "zebra":
63+
return new Hay(100);
64+
case "rabbit":
65+
return new Pellets(5);
66+
case "goat":
67+
return new Pellets(30);
68+
case "polar bear":
69+
return new Fish(10);
70+
}
71+
72+
// Good practice to throw an exception if no matching subclass could be
73+
// found
74+
throw new UnsupportedOperationException("Unsupported animal: " + animalName);
75+
}
76+
}
77+
78+
class ZooKeeper {
79+
public static void main(String[] args) {
80+
final Food food = FactoryPattern.getFood("polar bear");
81+
food.consumed();
82+
}
83+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package designPatternsAndPrinciples;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
/**
8+
*
9+
* @author chengfeili
10+
* Jun 5, 2017 9:47:23 PM
11+
*
12+
* The immutable object pattern is a creational pattern based on the
13+
* idea of creating objects whose state does not change after they are
14+
* created and can be easily shared across multiple classes.
15+
*
16+
* 1. Use a constructor to set all properties of the object.
17+
* 2. Mark all of the instance variables private and final.
18+
* 3. Don’t define any setter methods.
19+
* 4. Don’t allow referenced mutable objects to be modified or accessed directly.
20+
* 5. Prevent methods from being overridden.
21+
*
22+
*/
23+
public class ImmutableObject {
24+
private final String species;
25+
private final int age;
26+
private final List<String> favoriteFoods;
27+
28+
public ImmutableObject(String species, int age, List<String> favoriteFoods) {
29+
this.species = species;
30+
this.age = age;
31+
if (favoriteFoods == null) {
32+
throw new RuntimeException("favoriteFoods is required");
33+
}
34+
// User can modify the items in the List.
35+
// this.favoriteFoods = favoriteFoods;
36+
this.favoriteFoods = new ArrayList<String>(favoriteFoods);
37+
}
38+
39+
public String getSpecies() {
40+
return species;
41+
}
42+
43+
public int getAge() {
44+
return age;
45+
}
46+
47+
public int getFavoriteFoodsCount() {
48+
return favoriteFoods.size();
49+
}
50+
51+
public String getFavoriteFood(int index) {
52+
return favoriteFoods.get(index);
53+
}
54+
}
55+
56+
/*
57+
* How do we modify immutable objects if they are inherently unmodifiable? The
58+
* answer is, we can’t! Alternatively, we can create new immutable objects that
59+
* contain all of the same information as the original object plus whatever we
60+
* wanted to change.
61+
*/
62+
class ModifyImmutableObject {
63+
ImmutableObject lion = new ImmutableObject("lion", 5, Arrays.asList("meat", "more meat"));
64+
// Create a new Animal instance using data from the first instance
65+
List<String> favoriteFoods = new ArrayList<String>();
66+
{
67+
for (int i = 0; i < lion.getFavoriteFoodsCount(); i++) {
68+
favoriteFoods.add(lion.getFavoriteFood(i));
69+
}
70+
}
71+
}

Java-8/src/designPatternsAndPrinciples/ImplementingFunctionalInterfacesWithLambdas.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package designPatternsAndPrinciples;
22

3+
import java.util.List;
34
import java.util.function.Predicate;
45

56
/**
@@ -46,6 +47,10 @@ public Animal(String species, boolean canHop, boolean canSwim) {
4647
this.canSwim = canSwim;
4748
}
4849

50+
public Animal(String species2, int age, List<String> favoriteFoods) {
51+
// TODO Auto-generated constructor stub
52+
}
53+
4954
public boolean canHop() {
5055
return canHop;
5156
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package designPatternsAndPrinciples;
2+
3+
/**
4+
*
5+
* @author chengfeili
6+
* Jun 5, 2017 9:14:26 PM
7+
*
8+
* The single pattern is a creational pattern focused on creating only
9+
* one instance of an object in memory within an application, sharable
10+
* by all classes and threads with the application. The globally
11+
* available object created by the singleton pattern is referred to as a
12+
* singleton.
13+
*
14+
* Singletons are used in situations where we need access to a single
15+
* set of data throughout an application. For example, application
16+
* configuration data and reusable data caches are commonly implemented
17+
* using singletons. Singletons may also be used to coordinate access to
18+
* shared resources, such as coordinating write access to a file
19+
*/
20+
21+
// Method 1: Instantiate the singleton object directly in the definition of the instance reference.
22+
public class SingletonPattern1 {
23+
private int quantity = 0;
24+
25+
private SingletonPattern1() {
26+
}
27+
28+
private static final SingletonPattern1 instance = new SingletonPattern1();
29+
30+
public static SingletonPattern1 getInstance() {
31+
return instance;
32+
}
33+
34+
public synchronized void addHay(int amount) {
35+
quantity += amount;
36+
}
37+
38+
public synchronized boolean removeHay(int amount) {
39+
if (quantity < amount)
40+
return false;
41+
quantity -= amount;
42+
return true;
43+
}
44+
45+
public synchronized int getHayQuantity() {
46+
return quantity;
47+
}
48+
}
49+
50+
class LlamaTrainer {
51+
public boolean feedLlamas(int numberOfLlamas) {
52+
int amountNeeded = 5 * numberOfLlamas;
53+
SingletonPattern1 hayStorage = SingletonPattern1.getInstance();
54+
if (hayStorage.getHayQuantity() < amountNeeded) {
55+
hayStorage.addHay(amountNeeded + 10);
56+
}
57+
boolean fed = hayStorage.removeHay(amountNeeded);
58+
if (fed)
59+
System.out.println("Llamas have been fed");
60+
return fed;
61+
}
62+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package designPatternsAndPrinciples;
2+
3+
/**
4+
*
5+
* @author chengfeili
6+
* Jun 5, 2017 9:21:24 PM
7+
*
8+
*/
9+
10+
// Method 2: Instantiation using a static block
11+
public class SingletonPattern2 {
12+
private static final SingletonPattern2 instance;
13+
static {
14+
instance = new SingletonPattern2();
15+
// Perform additional steps
16+
}
17+
18+
private SingletonPattern2() {
19+
}
20+
21+
public static SingletonPattern2 getInstance() {
22+
return instance;
23+
}
24+
// Data access methods
25+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package designPatternsAndPrinciples;
2+
3+
/**
4+
*
5+
* @author chengfeili
6+
* Jun 5, 2017 9:26:12 PM
7+
*
8+
* Creating a reusable object the first time it is requested is a
9+
* software design pattern known as lazy instantiation.
10+
*/
11+
// Method 3: Lazy Instantiation. Delay creation of the singleton until the first
12+
// time the getInstance() method is called:
13+
14+
public class SingletonPattern3 {
15+
private static SingletonPattern3 instance;
16+
17+
private SingletonPattern3() {
18+
}
19+
20+
// 1. NOT THREAD-SAFE
21+
public static SingletonPattern3 getInstance() {
22+
if (instance == null) {
23+
instance = new SingletonPattern3();
24+
}
25+
return instance;
26+
}
27+
28+
/* 2. THREAD-SAFE
29+
*
30+
* has the problem that every single call to this method will require
31+
* synchronization. In practice, this can be costly and can impact
32+
* performance. Synchronization is only needed the first time that the
33+
* object is created.
34+
*/
35+
public static synchronized SingletonPattern3 getInstance2() {
36+
if (instance == null) {
37+
instance = new SingletonPattern3();
38+
}
39+
return instance;
40+
}
41+
42+
/* 3. Double-Checked Locking
43+
*
44+
* The solution is to use double‐checked locking, a design pattern in which
45+
* we first test if synchronization is needed before actually acquiring any
46+
* locks.
47+
*
48+
* Volatile prevents a subtle case where the compiler tries to optimize the
49+
* code such that that the object is accessed before it is finished being
50+
* constructed.
51+
*/
52+
private static volatile SingletonPattern3 instance3;
53+
54+
public static SingletonPattern3 getInstance3() {
55+
if (instance3 == null) {
56+
synchronized (SingletonPattern3.class) {
57+
if (instance3 == null) {
58+
instance3 = new SingletonPattern3();
59+
}
60+
}
61+
}
62+
return instance;
63+
}
64+
// Data access methods
65+
}

0 commit comments

Comments
 (0)