Sunday, September 20, 2015

Design Pattern Misc



The Principles of Good Programming
DRY - Don’t repeat yourself 
Abstraction Principle - Related to DRY is the abstraction principle “Each significant piece of functionality in a program should be implemented in just one place in the source code.”http://en.wikipedia.org/wiki/Abstraction_principle_(programming)
KISS (Keep it simple, stupid!) - Simplicity (and avoiding complexity) should always be a key goal. Simple code takes less time to write, has fewer bugs, and is easier to modify.http://en.wikipedia.org/wiki/KISS_principle
Avoid Creating a YAGNI (You aren’t going to need it) - You should try not to add functionality until you need it. http://en.wikipedia.org/wiki/YAGNI
Do the simplest thing that could possibly work - A good question to ask one’s self when programming is “What is the simplest thing that could possibly work?” This helps keep us on the path towards simplicity in the design. http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html
Don’t make me think - This is actually the title of a book by Steve Krug on web usability that is also relevant in programming. The point is that code should be easily read and understood with a minimum of effort required. If code requires too much thinking from an observer to understand, then it can probably stand to be simplifiedhttp://www.sensible.com/dmmt.html
Open/Closed Principle - Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. In other words, don't write classes that people can modify, write classes that people can extendhttp://en.wikipedia.org/wiki/Open_Closed_Principle
Write Code for the Maintainer - Almost any code that is worth writing is worth maintaining in the future, either by you or by someone else. The future you who has to maintain code often remembers as much of the code, as a complete stranger, so you might as well always write for someone else. A memorable way to remember this is “Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.” http://c2.com/cgi/wiki?CodeForTheMaintainer
Principle of least astonishment - The principle of least astonishment is usually referenced in regards to the user interface, but the same principle applies to written code. Code should surprise the reader as little as possible. The means following standard conventions, code should do what the comments and name suggest, and potentially surprising side effects should be avoided as much as possiblehttp://en.wikipedia.org/wiki/Principle_of_least_astonishment
Single Responsibility Principle - A component of code (e.g. class or function) should perform a single well defined task. http://en.wikipedia.org/wiki/Single_responsibility_principle
Minimize Coupling - Any section of code (code block, function, class, etc) should minimize the dependencies on other areas of code. This is achieved by using shared variables as little as possible. “Low coupling is often a sign of a well-structured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability” http://en.wikipedia.org/wiki/Coupling_(computer_programming)
Maximize Cohesion - Code that has similar functionality should be found within the same component. http://en.wikipedia.org/wiki/Cohesion_(computer_science)
Hide Implementation Details - Hiding implementation details allows change to the implementation of a code component while minimally affecting any other modules that use that component. http://en.wikipedia.org/wiki/Information_Hiding
Law of Demeter - Code components should only communicate with their direct relations (e.g. classes that they inherit from, objects that they contain, objects passed by argument, etc.)http://en.wikipedia.org/wiki/Law_of_Demeter
Avoid Premature Optimization - Don’t even think about optimization unless your code is working, but slower than you want. Only then should you start thinking about optimizing, and then only with the aid of empirical data. "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" - Donald Knuth.http://en.wikipedia.org/wiki/Program_optimization
Code Reuse is Good - Not very pithy, but as good a principle as any other. Reusing code improves code reliability and decrease development time.http://en.wikipedia.org/wiki/Code_reuse
Separation of Concerns - Different areas of functionality should be managed by distinct and minimally overlapping modules of code. http://en.wikipedia.org/wiki/Separation_of_concerns
Embrace Change -

Occam's Razor
"When you have two competing solutions to the same problem, the simpler one is the better."

SOLID - Robert C. Martin
Single Responsibility Principle: A class should have only a single reason to change.
Open-Closed Principle: A class should be open for extension and closed for modification. This is attributed to Bertrand Meyer.
Liskov Substitution Principle: This was created by Barbara Liskov, and she says a class should be replaceable by others that extend that class.
Interface Segregation Principle: A few specific interfaces are preferable than one general-purpose interface.
Dependency Inversion Principle: A class should depend on abstraction instead of implementation. This means that class dependencies must be focused on what is done and forget about how it is done.


http://www.baeldung.com/java-strategy-pattern
This advantage becomes more apparent when we want to declare even more Discounters in line:
1
2
3
4
5
List<Discounter> discounters = newArrayList(
  amount -> amount.multiply(BigDecimal.valueOf(0.9)),
  amount -> amount.multiply(BigDecimal.valueOf(0.8)),
  amount -> amount.multiply(BigDecimal.valueOf(0.5))
);
When we want to define lots of Discounters, we can declare them statically all in one place. Java 8 even lets us define static methods in interfaces if we want to.
So instead of choosing between concrete classes or anonymous inner types, let’s try creating lambdas all in a single class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface Discounter {
    BigDecimal applyDiscount(BigDecimal amount);
    static Discounter christmasDiscounter() {
        return amount -> amount.multiply(BigDecimal.valueOf(0.9));
    }
    static Discounter newYearDiscounter() {
        return amount -> amount.multiply(BigDecimal.valueOf(0.8));
    }
    static Discounter easterDiscounter() {
        return amount -> amount.multiply(BigDecimal.valueOf(0.5));
    }
}

3.2. Leveraging Function Composition

Let’s modify our Discounter interface so it extends the UnaryOperator interface, and then add a combine() method:
1
2
3
4
5
public interface Discounter extends UnaryOperator<BigDecimal> {
    default Discounter combine(Discounter after) {
        return value -> after.apply(this.apply(value));
    }
}
Essentially, we are refactoring our Discounter and leveraging a fact that applying a discount is a function that converts a BigDecimal instance into another BigDecimal instanceallowing us to access predefined methodsAs the UnaryOperator comes with an apply() method, we can just replace applyDiscount with it.

Now, Let’s try applying multiple Discounters cumulatively to an amount. We will do this by using the functional reduce() and our combine():
1
2
3
4
5
Discounter combinedDiscounter = discounters
  .stream()
  .reduce(v -> v, Discounter::combine);
combinedDiscounter.apply(...);
Pay special attention to the first reduce argument. When no discounts provided, we need to return the unchanged value. This can be achieved by providing an identity function as the default discounter.

https://dzone.com/articles/strategy-pattern-using-lambda
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
    List<Strategy> strategies = 
      Arrays.asList(
        () -> {System.out.println("Perform task a day before deadline!");},
        () -> {System.out.println("Perform task now!");}
      );
    
    strategies.forEach((elem) -> elem.performTask());
    List<Computation<Integer>> computations = 
          Arrays.asList(
              (n, m)-> { return n+m; },
              (n, m)-> { return n*m; },
              (n, m)-> { return n-m; }
          );
    computations.forEach((comp) -> System.out.println(comp.compute(10, 4)));
  }

https://jaxenter.com/patterns-java-8-lambdas-127635.html
Spring framework is often the target of a gazillion jokes just for having a class named SimpleBeanFactoryAwareAspectInstanceFactory, even if the name is actually well chosen: You’ll get a factory that produces instances of aspects by using another factory.

        
final Supplier<Computation> slowFactory = () -> n -> {
            long rv = 0L;
            for (long i = 1; i <= n; ++i) {
                rv += i;
            }
            return rv;
        };
         
        final Supplier<Computation> gaussFactory = () -> n -> (n * (n+1))/2;
        System.out.println(slowFactory.get().sum1To(100));
        System.out.println(gaussFactory.get().sum1To(100));

Builders are often used together with fluent APIs or small, domain specific languages (DSLs) to create immutable objects without “telescoping” constructors (a telescoping constructor occurs when the increase of object constructor parameter combination leads to an exponential list of overloaded constructors).
The builder pattern is often used to configure things. Configuration often depends on a well-defined order of steps. The ideal implementation of a builder for me consists of a readable API, respecting the order of steps and resulting in an immutable object. Also, the builder used should be used only for one purpose.
https://www.linkedin.com/pulse/welcome-factory-pattern-using-lambda-expressions-java-saral-saxena/
http://www.jiffle.net/blog/2017/04/02/the-factory-pattern-using-java-8-lambda-evolved/
public class ShapeFactory {
   @RequiredArgsConstructor
   @Getter( AccessLevel.PRIVATE)
   public static enum ShapeType {
      CIRCLE( Circle::new),
      RECTANGLE( Rectangle::new);

      private final Supplier<Shape> constructor;
   }

   public static Shape createShape( ShapeType type) {
      return type.getConstructor().get();
   }
}

public class ShapeFactory {
   @RequiredArgsConstructor
   @Getter( AccessLevel.PRIVATE)
   public static enum ShapeType {
      CIRCLE( (c, t) -> new Circle( c, t)),
      RECTANGLE( (c, t) -> new Rectangle( c, t));

      private final ShapeConstructor constructor;
   }

   @FunctionalInterface
   private interface ShapeConstructor {
      Shape create( Color colour, int thickness);
   }

   public static Shape createShape( ShapeType type, Color colour, int thickness) {
      return type.getConstructor().create( colour, thickness);
   }
}
To me, this is where this gets really interesting. One of the main reasons to use the factory pattern is to decouple the points where the factory type is selected and where the instances are created. Ideally what we’d like to do is to construct the right type of factory in one part of the code, and then invoke the construction with parameters within a service that uses it.
We can do that here by changing the static factory method to return a lambda that constructs the instance. Conveniently, that is exactly the function signature that we already use in the enums.
This allows us to move the functional interface to the top-level class (since static methods are supported in Java 8). That static method also now becomes trivial, as it merely delegates to the getter in the relevant enum.
@FunctionalInterface
public interface ShapeFactory {
   @RequiredArgsConstructor
   @Getter( AccessLevel.PRIVATE)
   public static enum ShapeType {
      CIRCLE( (c, t) -> new Circle( c, t)),
      RECTANGLE( (c, t) -> new Rectangle( c, t));

      private final ShapeFactory constructor;
   }

   Shape create( Color colour, int thickness);

   static ShapeFactory createFactory( ShapeType type) {
      return type.getConstructor();
   }
}

https://dzone.com/articles/factory-pattern-using-lambda-expression-in-java-8
Create a Factory to generate an object of your concrete classes based on given information.
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();         
      }       
      return null;
   }

In Java 8, we can refer to constructors just like we refer to methods, by using
method references. For example, here’s how to refer to the Circle constructor:
Supplier<Shape> circleSupplier = Circle::new;
Circle circle = circleSupplier.get();
public class ShapeFactory {
  final static Map<String, Supplier<Shape>> map = new HashMap<>();
  static {
    map.put("CIRCLE", Circle::new);
    map.put("RECTANGLE", Rectangle::new);
  }   
  public Shape getShape(String shapeType){
     Supplier<Shape> shape = map.get(shapeType.toUpperCase());
     if(shape != null) {
       return shape.get();
     }
     throw new IllegalArgumentException("No such shape " + shapeType.toUpperCase());
  }
}
But this technique doesn’t scale very well if the factory method getShape
needs to take multiple arguments to pass on to the Shape constructors! You’d have to provide
a different functional interface than a simple Supplier.

https://dzone.com/articles/template-method-pattern-using
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. TemplateMethod lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
Template Method pattern can be applied to above scenario by encapsulating the workflow system into an abstract class with few of the tasks out of the 4 tasks implemented. And leave the implementation of remaining tasks to the subclasses of the abstract class.

https://www.voxxed.com/2016/04/gang-four-patterns-functional-light-part-1/
public static void publishText( String text, Predicate<String> filter, UnaryOperator<String> format) {
    if (filter.test( text )) {
        System.out.println( format.apply( text ) );
    }
}
https://www.voxxed.com/2016/05/gang-four-patterns-functional-light-part-2/
public static void withResource( Consumer<Resource> consumer) {
    Resource resource = new Resource();
    try {
        consumer.accept( resource );
    finally {
        resource.dispose();
    }
}

public class Observable {
    private final Map<Object, Consumer<Object>> listeners = new ConcurrentHashMap<>();
    public void register(Object key, Consumer<Object> listener) {
        listeners.put(key, listener);
    }
    public void unregister(Object key) {
        listeners.remove(key);
    }
    public void sendEvent(Object event) {
        listeners.values().forEach( listener -> listener.accept( event ) );
    }
}

Observable observable = new Observable();
observable.register( "key1", e -> System.out.println(e) );
observable.register( "key2", System.out::println );
observable.sendEvent( "Hello World!" );

https://www.voxxed.com/2016/05/gang-four-patterns-functional-light-part-3/
The Decorator pattern allows to dynamically extend the functionality of an existing object by wrapping it with multiple nested layers. All these layers have to implement the same interface in order to allow their composition.
public abstract class AbstractTaxDecorator implements SalaryCalculator {
    private final SalaryCalculator salaryCalculator;
    public AbstractTaxDecorator( SalaryCalculator salaryCalculator ) {
        this.salaryCalculator = salaryCalculator;
    }
    protected abstract double applyTax(double salary);
    @Override
    public final double calculate(double gross) {
        double salary = salaryCalculator.calculate( gross );
        return applyTax( salary );
    }
}
The advantage of this pattern is evidently in the fact that it allows to easily add and remove different decorators and then choose the taxes that should or shouldn't be applied for a certain salary calculation. The drawback, not considering the verbose implementation, is that the computation proceeds from the most internal calculator to the external ones and then the decorators have to be written in reverse order.

public class DefaultSalaryCalculator implements DoubleUnaryOperator {
    @Override
    public double applyAsDouble(double grossAnnual) {
        return grossAnnual / 12;
    }
}
the essence of the Decorator pattern. What it actually does it is offering a way to compose different computations, but functions composition is of course something that is far more natural in functional programming. It's almost surprising that we can achieve exactly the same result that costed us so many efforts using the Decorator pattern in a trivial way as it follows:
?
1
2
3
4
5
double netSalary = new DefaultSalaryCalculator()
        .andThen( Taxes::generalTax )
        .andThen( Taxes::regionalTax )
        .andThen( Taxes::healthInsurance )
        .applyAsDouble( 30000.00 );
public static double calculate(double gross, DoubleUnaryOperator... fs) {
    return Stream.of( fs )
                 .reduce( DoubleUnaryOperator.identity(),
                          DoubleUnaryOperator::andThen )
                 .applyAsDouble( gross );
}

The Chain of Responsibility pattern

This pattern consists in creating a sequence of objects that are designed to process an input. Each object in the chain could, or could not, be able to process a specific input. If a processing object has been designed for the input at hand it will do so, otherwise it will pass the input down to the next object of the chain. If the last object of the chain also isn't able to process a given input, the chain will fail silently, or more commonly, will notify the user of the failure with an Exception

public static Optional<String> parseText(File file) {
    return file.getType() == File.Type.TEXT ?
           Optional.of("Text file: " + file.getContent()) :
           Optional.empty();
}

String result = Stream.<Function<File, Optional<String>>>of( // [1]
        ChainOfRespLambda::parseText,
        ChainOfRespLambda::parseAudio,
        ChainOfRespLambda::parseVideo )
        .map(f -> f.apply( file )) // [2]
        .filter( Optional::isPresent ) // [3]
        .findFirst() // [4]
        .flatMap( Function.identity() ) // [5]
        .orElseThrow( () -> new RuntimeException( "Unknown file: " + file ) ) ); 
https://www.voxxed.com/2016/05/gang-four-patterns-functional-light-part-4/
The Interpreter pattern is commonly used when it is required to evaluate expressions written in a specific formalism. 
String expression = "7 3 - 2 1 + *";
public static int evaluate(String expression) {
    Stack<Expression> stack = new Stack<>();
    for (String s : expression.split(" ")) {
        if (isOperator(s)) {
            Expression right = stack.pop();
            Expression left = stack.pop();
            stack.push(getOperator(s, left, right));
        else {
            Expression i = new Number(Integer.parseInt(s));
            stack.push(i);
        }
    }
    return stack.pop().interpret();
}

static Map<String, IntBinaryOperator> opMap = new HashMap<>();
static {
    opMap.put("+", (a, b) -> a + b);
    opMap.put("*", (a, b) -> a * b);
    opMap.put("-", (a, b) -> a - b);
}

public static int evaluate(String expression) {
    Stack<Integer> stack = new Stack<>();
    for (String s : expression.split(" ")) {
        IntBinaryOperator op = opMap.get( s );
        if (op != null) {
            int right = stack.pop();
            int left = stack.pop();
            stack.push(op.applyAsInt( left, right ));
        else {
            stack.push(Integer.parseInt(s));
        }
    }
    return stack.pop();
}

the Visitor pattern is commonly used when it is required to add new operations to existing objects but it’s impossible (or not wanted for design reason) to modify the objects themselves and add the missing operations directly inside their implementation. To allow this each object of our domain must have a method accepting a Visitor and passing itself to the that Visitor and then have to implement an interface like the following.

http://colobu.com/2014/09/05/design-pattern-cheatsheet/
http://stackoverflow.com上一个帖子,总结了Java SE和 Java EE中实现的设计模式。
以及Design Patterns in the JDK

还有PDF版的
design patterndesign pattern

JDK中设计模式的实现

Creational patterns

Abstract factory (recognizeable by creational methods returning the factory itself which in turn can be used to create another abstract/interface type)

Builder (recognizeable by creational methods returning the instance itself)

Factory method (recognizeable by creational methods returning an implementation of an abstract/interface type)

Prototype (recognizeable by creational methods returning a different instance of itself with the same properties)

Singleton (recognizeable by creational methods returning the same instance (usually of itself) everytime)


Structural patterns

Adapter (recognizeable by creational methods taking an instance of different abstract/interface type and returning an implementation of own/another abstract/interface type which decorates/overrides the given instance)

Bridge (recognizeable by creational methods taking an instance of different abstract/interface type and returning an implementation of own abstract/interface type which delegates/uses the given instance)


  • None comes to mind yet. A fictive example would be new LinkedHashMap(LinkedHashSet<K>, List<V>)which returns an unmodifiable linked map which doesn't clone the items, but uses them. Thejava.util.Collections#newSetFromMap() and singletonXXX() methods however comes close.

Composite (recognizeable by behavioral methods taking an instance of same abstract/interface type into a tree structure)

Decorator (recognizeable by creational methods taking an instance of same abstract/interface type which adds additional behaviour)

Facade (recognizeable by behavioral methods which internally uses instances of different independent abstract/interface types)

Flyweight (recognizeable by creational methods returning a cached instance, a bit the "multiton" idea)

Proxy (recognizeable by creational methods which returns an implementation of given abstract/interface type which in turn delegates/uses a different implementation of given abstract/interface type)

The Wikipedia example is IMHO a bit poor, lazy loading has actually completely nothing to do with the proxy pattern at all.

Behavioral patterns

Chain of responsibility (recognizeable by behavioral methods which (indirectly) invokes the same method in another implementation of same abstract/interface type in a queue)

Command (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a different abstract/interface type which has been encapsulated by the command implementation during its creation)

Interpreter (recognizeable by behavioral methods returning a structurally different instance/type of the given instance/type; note that parsing/formatting is not part of the pattern, determining the pattern and how to apply it is)

Iterator (recognizeable by behavioral methods sequentially returning instances of a different type from a queue)

Mediator (recognizeable by behavioral methods taking an instance of different abstract/interface type (usually using the command pattern) which delegates/uses the given instance)

Memento (recognizeable by behavioral methods which internally changes the state of the whole instance)

Observer (or Publish/Subscribe) (recognizeable by behavioral methods which invokes a method on an instance of another abstract/interface type, depending on own state)

State (recognizeable by behavioral methods which changes its behaviour depending on the instance's state which can be controlled externally)

Strategy (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a different abstract/interface type which has been passed-in as method argument into the strategy implementation)

Template method (recognizeable by behavioral methods which already have a "default" behaviour definied by an abstract type)

Visitor (recognizeable by two different abstract/interface types which has methods definied which takes each theother abstract/interface type; the one actually calls the method of the other and the other executes the desired strategy on it)

Spring 框架中都用到了哪些设计模式?
1、代理模式—在AOP和remoting中被用的比较多。
2、单例模式—在spring配置文件中定义的bean默认为单例模式。
3、模板方法—用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
4、前端控制器—Spring提供了DispatcherServlet来对请求进行分发。

5、视图帮助(View Helper )—Spring提供了一系列的JSP标签,高效宏来辅助将分散的代码整合在视图里。
6、依赖注入—贯穿于BeanFactory / ApplicationContext接口的核心理念。
7、工厂模式—BeanFactory用来创建对象的实例。




Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts