您的位置:首页 > 编程语言 > Java开发

Java Construction Patterns

2018-01-15 10:00 323 查看
Over the years a couple of well-understood and widely applicable construction (or creation) patterns have emerged within Java community. We are going to cover the most famous of them: singleton, helpers, factory and dependency injection (also known as inversion of control).

Singleton

最基本的单例,线程不安全。私有静态实例,私有的构造方法,共有的静态getInstance

public class NaiveSingleton {

private static NaiveSingleton instance;

private NaiveSingleton() {
}

public static NaiveSingleton getInstance() {
if (instance == null) {
instance = new NaiveSingleton();
}
return instance;
}
}


用 static final 改进的单例,类加载的时候构建,线程安全。

public class EagerSingleton {

private static final EagerSingleton instance = new EagerSingleton();

private EagerSingleton() {
}

public static EagerSingleton getInstance() {
return instance;
}
}


延迟加载,仅仅在第一次需要的时候创建

public class LazySingleton {

private static LazySingleton instance;

private LazySingleton() {
}

public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}


Nowadays, singletons are not considered to be a good choice in most cases, primarily because they are making a code very hard to test. The domination of dependency injection pattern (please see the Dependency Injection section below) also makes singletons unnecessary.

Utility/Helper Class

The utility or helper classes are quite popular pattern used by many Java developers. Basically, it represents the non-instantiable class (with constructor declared as private), optionally declared as final and contains static methods only.

From seasoned software developer standpoint, such helpers often become containers for all kind of non-related methods which have not found other place to be put in but should be shared somehow and used by other classes. Such design decisions should be avoided in most cases: it is always possible to find another way to reuse the required functionality, keeping the code clean and concise.

public final class HelperClass {

private HelperClass() {
}

public static void helperMethod1() {
// Method body here
}

public static void helperMethod2() {
// Method body here
}
}


Factory

Factory pattern is proven to be extremely useful technique in the hands of software developers. As such, it has several flavors in Java, ranging from factory method to abstract factory. The simplest example of factory pattern is a static method which returns new instance of a particular class (factory method).

public class Book {

private Book(final String title) {
}

public static Book newBook(final String title) {
return new Book(title);
}
}


The one may argue that it does not make a lot of sense to introduce the newBook factory method but using such a pattern often makes the code more readable. Another variance of factory pattern involves interfaces or abstract classes (abstract factory) with couple of different implementations, depending on the library type. For example, let us define a factory interface:

public interface BookFactory {
Book newBook();
}


public class Library implements BookFactory {
@Override
public Book newBook() {
return new PaperBook();
}
}

public class KindleLibrary implements BookFactory {
@Override
public Book newBook() {
return new KindleBook();
}
}


Now, the particular class of the Book is hidden behind BookFactory interface implementation, still providing the generic way to create books.

Dependency Injection

Dependency injection (also known as inversion of control) is considered as a good practice for class designers: if some class instance depends on the other class instances, those dependencies should be provided (injected) to it by means of constructors (or setters, strategies, etc.) but not created by the instance itself. Let us consider the following example:

public class Dependant {

private final DateFormat format = DateFormat.getDateInstance();

public String format(final Date date) {
return format.format(date);
}
}


The class Dependant needs an instance of DateFormat and it just creates one by calling DateFormat.getDateInstance() at construction time. The better design would be to use constructor argument to do the same thing:

public class Dependant {

private final DateFormat format;

public Dependant(final DateFormat format) {
this.format = format;
}

public String format(final Date date) {
return format.format(date);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息