The login
registered
Write an article
Home page
Download the APP
Design Pattern Learning Summary (1)
AxeChen
Design Pattern Learning Summary (1)
Learning design patterns was a Java foundation that I used to review when I was looking for a job. Reference “Android source code design pattern analysis and combat” book and other bloggers blog, plus their own understanding and summary, there is this blog.
Design mode can be said to be closely related to every developer. For example, an Android developer uses the setAdapter and NotifidatasetChange methods of RecyclerView to use the adapter mode and the observer mode. At the same time, if you want to become an architect, This knowledge of design patterns will also help you when building frameworks.
Currently there are 23 design patterns, these are currently accepted, my understanding is: If you have a better idea, you can also write a better design pattern. MVC, MVP and other architectural methods are all inspired by others and then widely popular. Of course, not all design patterns are perfect, and each design pattern has advantages and disadvantages.
This article introduces some design patterns:
- Constructor model
- The factory pattern
- Chain of Responsibility model
- Observer model
- The prototype pattern
- The proxy pattern
- The singleton pattern
- The state pattern
- The strategy pattern
- Adapter mode
After learning other design patterns, you can add a blog post (2).
1. Constructor pattern
If you have used Retorfit, OKHttp, etc., you will be familiar with the following code.
Public void init() {// Initialize okhttp OkHttpClient client = new okHttpClient.builder.build (); // Initialize Retrofit Retrofit = new retrofit.builder ().client(client).baseurl (request.host) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); }Copy the code
The initialization of Retrofit is a typical constructor pattern.
1.1. Definition of constructor pattern
Separating the construction of a complex object from its initialization allows the same construction process to create different representations.
1.2. Implement ImageLoader with constructor mode.
Let’s start with a quick analysis of what you need to have in order to implement an ImageLoader.
The structure of the ImageLoader
The sample does only a few configurations for the caching mechanism and downloader required for ImageLoader. ImageLoader is a highly extensible image framework. What stands out is that most of the components in ImageLoader can be customized as long as they conform to the interface specifications defined by ImageLoader. Define an ImageLoaderConfig class to configure the ImageLoader parameters.
package com.axe.builder.imageloader; ** @author 11373 ** / public class ImageLoaderConfig {/** ** public Boolean useMemoryCache = false; Public Boolean useCustomMemoryCache = false; Public Boolean useDiskCache = false; /** * Public Boolean useCustomDiskCache = false; Public Boolean useCustomDownLoader = false; /** * public Cache memoryCache; /** * public Cache diskCache; /** * DownLoader */ public DownLoader; /** * constructor ** @author 11373 ** / public static class Builder {/** ** public Cache memoryCache; /** * public Cache diskCache; /** * DownLoader */ public DownLoader; public boolean useMemoryCache = false; public boolean useDiskCache = false; public Builder setDownLoader(DownLoader downLoader) { this.downLoader = downLoader; return this; } public Builder setMemoryCache(Cache memoryCache) { this.memoryCache = memoryCache; return this; } public Builder setDiskCache(Cache diskCache) { this.diskCache = diskCache; return this; } public Builder userMemoryCache(boolean flag) { this.useMemoryCache = flag; return this; } public Builder useDiskCache(boolean flag) { this.useDiskCache = flag; return this; } public void applyConfig(ImageLoaderConfig config) { if (useMemoryCache) { config.useMemoryCache = true; if (memoryCache ! = null) { config.memoryCache = memoryCache; } else {// if no external memoryCache policy is passed in, use the default config.memorycache = new memoryCache (); } } if (useDiskCache) { config.useDiskCache = true; if (diskCache ! = null) { config.diskCache = diskCache; } else {config.diskCache = new diskCache ();} else {config.diskCache = new diskCache (); } } if (downLoader ! = null) { config.downLoader = downLoader; config.useCustomDownLoader = true; } else {// If no external memory cache is passed in, use the default config.downloader = new DeFaultDownLoader(); } } public ImageLoaderConfig create() { ImageLoaderConfig config = new ImageLoaderConfig(); applyConfig(config); return config; }}}Copy the code
The ImageLoader class is only used to download images. Its core method is displayImage, and all its configuration comes from ImageLoaderConfig:
package com.axe.builder.imageloader; Public class ImageLoader {private ImageLoaderConfig config; private static ImageLoader imageLoader; private ImageLoader() { } public static ImageLoader getInstance() { if (imageLoader == null) { synchronized (ImageLoader.class) { if (imageLoader == null) { imageLoader = new ImageLoader(); } } } return imageLoader; } public void init(ImageLoaderConfig config) {this.config = config; } public void displayImage(String url, ImageView image) { Bitmap bitmap = null; // If memory caching is set, memory caching is used. if (bitmap == null && config.useMemoryCache) { bitmap = config.memoryCache.getBitmap(url); } // Set the disk cache. if (bitmap == null && config.useDiskCache) { bitmap = config.diskCache.getBitmap(url); } / / if the memory and disk can't find the picture, then go to download the if (bitmap = = null) {config. The downLoader. DownloadImage (url); } image.setBitmap(bitmap); }}Copy the code
Initialize and use:
public class BuilderMain {
public static void main(String[] args) {
ImageLoaderConfig config = new Builder()
.setDiskCache(new AxeDiskCache())
.setMemoryCache(new AxeMemoryCache())
.useDiskCache(true)
.userMemoryCache(true)
.setDownLoader(new AxeImageLoader())
.create();
ImageLoader loader = ImageLoader.getInstance();
loader.init(config);
// 使用
loader.displayImage("", null);
}
}
Copy the code
1.3 advantages and disadvantages of the constructor model
Advantages: Good encapsulation, using the constructor pattern can keep the client from knowing the composition details inside the product. The constructors exist independently and are easy to expand. Disadvantages: Creates redundant constructor objects and consumes memory.
2. Factory mode
2.1. Factory method mode
In simple terms, this is an object-oriented polymorphic implementation, which creates an interface for creating objects. It is up to the subclass to decide what interface to create. It’s like there’s a factory that builds cars, and there’s a BMW factory and a Mercedes factory that does it, and whether you build a BMW or a Mercedes depends on those two methods.
- Create a car implementation class that encapsulates the car’s public method, drive.
public interface Car {
void drive();
}
Copy the code
Public class BenziCar implements Car {@override public void drive() {system.out.println (" BenziCar "); }}Copy the code
Public class BWMCar implements Car{@override public void drive() {system.out.println (" implements Car "); }}Copy the code
- To create a public method, there’s a public property which is to create a car. And then the Mercedes factory and the BMW factory inherit it, and they both have a common method, which is to create cars, which is to create objects.
public interface Factory {
Car createCar();
}
Copy the code
public class BenziFactory implements Factory{ @Override public Car createCar() { return new BenziCar(); }}Copy the code
public class BWMCarFactory implements Factory { @Override public Car createCar() { return new BWMCar(); }}Copy the code
Actual use:
public class FactoryMain { public static void main(String[] args) { Factory benziFactory = new BenziFactory(); benziFactory.createCar().drive(); Factory bwmFactory = new BWMCarFactory(); bwmFactory.createCar().drive(); }}Copy the code
Driving a Mercedes and a BMWCopy the code
Advantages and disadvantages of the factory method pattern
- Advantages: in line with the open and closed principle. When new products are added, only the corresponding specific product class and the corresponding factory subclass can be added; Consistent with the principle of single responsibility. Each concrete factory class is only responsible for creating the corresponding product. (This article is from blog: Android Design Pattern – Factory Method Pattern)
- Disadvantages: a specific factory can only create a specific product; When new products are added, corresponding factory classes need to be added. The number of system classes will increase in pairs, which increases the complexity and performance overhead of the system. The introduction of abstract classes can also complicate the class structure. (This article is from blog :Android Design Pattern – Factory Method Pattern)
2.2. Simple Factory model
Continuing with the example in 2.1, we turned all of our implemented car factories into one factory that could generate a variety of different cars. Modify the base class of the car factory as follows:
public interface Factory2 {
Car createCar(String name);
}
Copy the code
We simply pass in the name of the car we want to generate, and we can generate the object of the modified car. The implementation class is as follows:
public class CarFactory implements Factory2 { @Override public Car createCar(String name) { if ("benzi".equals(name)) { return new BenziCar(); } else if ("bwm".equals(name)) { return new BWMCar(); } return null; }}Copy the code
In actual use:
Factory2 factory2 = new CarFactory();
factory2.createCar("benzi").drive();
factory2.createCar("bwm").drive();
Copy the code
There is another way to implement this communal factory:
public class CarFactory2 { public static <T extends Car> T createCar(Class<T> clz) { Car car = null; try { car = (Car) Class.forName(clz.getName()).newInstance(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return (T) car; }}Copy the code
In actual use:
CarFactory2 factory3 = new CarFactory2();
factory3.createCar(BenziCar.class).drive();
factory3.createCar(BWMCar.class).drive();
Copy the code
Advantages and disadvantages of the simple factory model
- Advantages: Code is decoupled, instance creation is separated from instance use, and consumers don’t have to care how class objects are created.
- Disadvantages: As you can see from the first implementation, it adds a lot of if judgment, which is not easy to maintain when there are more objects to produce; Violating the open and closed principle, if new products need to be added, the factory logic must be modified, which will cause too complex factory logic; The simple factory pattern uses static factory methods, so static methods cannot be inherited or overridden; The factory class contains the creation logic for all instances (products), and if the factory class fails, the entire system will be affected. (This article is from blog: Android Design Pattern – Factory Method Pattern)
2.3 abstract factory pattern
Some parts of a car built today must be made by a variety of different manufacturers. The engines and wheels of BMW and Mercedes cars are not produced by the same manufacturer, so if all the factories of these parts are also abstracted, the code is shown as follows:
public interface Engine {
void getEngine();
}
public interface Wheel {
void getWheel();
}
Copy the code
Parts implementation class:
Public implements Wheel{@override public void getWheel() {system.out.println (" implements Wheel "); }} public implements Wheel{@override public void getWheel() {system.out.println (" implements Wheel "); }} public implements Engine {@override public void getEngine() {system.out.println (" implements Engine "); }} public implements Engine {@override public void getEngine() {system.out.println ("AWM Engine "); }}Copy the code
Create a car interface:
public interface Factory3 {
Wheel createWheel();
Engine createEngine();
}
Copy the code
Specific realization of BMW and Mercedes-benz:
public class BenziCarFactory implements Factory3 { @Override public Wheel createWheel() { return new AKMWheel(); } @Override public Engine createEngine() { return new M24Engine(); } } public class BWMCarsFactory implements Factory3{ @Override public Wheel createWheel() { return new M416Wheel(); } @Override public Engine createEngine() { return new AWMEngine(); }}Copy the code
Specific use:
System.out.println(" create BMW "); Factory3 bwFactory = new BWMCarsFactory(); bwFactory.createEngine().getEngine(); bwFactory.createWheel().getWheel(); System.out.println(" create Mercedes "); Factory3 bzFactory = new BenziCarFactory(); bzFactory.createEngine().getEngine(); bzFactory.createWheel().getWheel();Copy the code
Create BMW AWM engine M426 wheels create Mercedes M24 engine AKM wheelsCopy the code
Advantages and disadvantages of the abstract factory pattern
- Advantages: Code is decoupled, instance creation is separated from instance use, and consumers don’t have to care how class objects are created.
- Disadvantages: If a new product is added, the abstract factory and all concrete factories are modified, which violates the open and closed principle.
3. Strategy mode
Keep using league of Legends as an example.
There are many ways to obtain bounty in this game, such as: kill wild monsters, kill heroes, kill minions and so on. If I had to write a way to calculate the bounty, what would I do?
package com.axe.strategy; /** * @author 11373 ** / public class Bounty {/** * public static final int batmam = 0; /** * hero */ public static final int TYPE_HERO = 1; /** * public final static int TYPE_MONSTER = 2; Public static final int TYPE_DRAGON = 1; @param count * @return */ public int killGetMoney(int type, int count) { int sum = 0; if (type == TYPE_BATMAM) { sum += getBatmanMoney(count); } else if (type == TYPE_HERO) { sum += getHeroMoney(count); } else if (type == TYPE_MONSTER) { sum += getMonsterMoney(count); } else if (type == TYPE_DRAGON) { sum += getDragonMoney(count); } return sum; } private int getBatmanMoney(int count) {return count * 30; } private int getHeroMoney(int count) {return count * 300; Private int getMonsterMoney(int count) {private int getMonsterMoney(int count); } private int getDragonMoney(int count) {return count * 500; }}Copy the code
In actual use:
Bounty bounty = new Bounty();
int getMoney = bounty.killGetMoney(Bounty.TYPE_BATMAM, 10) + bounty.killGetMoney(Bounty.TYPE_HERO, 1)
+ bounty.killGetMoney(Bounty.TYPE_MONSTER, 6);
Copy the code
It doesn’t seem like a big problem, and it’s pretty neat. But if this were a real league of Legends example, would it be so simple? For example: League of Legends kill wild monsters, wild monsters have many kinds, the bounty is not the same; When you kill a hero, it doesn’t have to be 300 gold coins. There are also ancillary equipment that will make the coins different. And there’s got to be more to it than that. For example, there is gold for pushing down the defense tower, there is gold for pushing down the crystal, etc. For all the calculations, the Bounty class would be huge, with a lot of logical decisions.
@param count * @return */ public int killGetMoney(int type, int count) { int sum = 0; if (type == TYPE_BATMAM) { sum += getBatmanMoney(count); } else if (type == TYPE_HERO) { sum += getHeroMoney(count); } else if (type == TYPE_MONSTER) { sum += getMonsterMoney(count); } else if (type == TYPE_DRAGON) { sum += getDragonMoney(count); } return sum; }Copy the code
This method has many if nesting layers. Too many if conditions are absolutely painful to maintain and lead to more errors! How do you write it if you use the policy pattern to optimize?
- Define the rules to be given for obtaining a bounty
@author 11373 ** / public interface GetMoney {public int GetMoney (int count); }Copy the code
- Inherit the interface for each type of method that gets the bounty
@author 11373 ** / public BatmanCalculater implements GetMoney {@override public GetMoney (int count) { return count * 30; }}Copy the code
- Defines a class to control how the bounty is acquired
/** * @author 11373 ** / public class calculater {private GetMoney GetMoney; public int getBountyMoney(int count) { return getMoney.getMoney(count); } public void setGetMoney(GetMoney getMoney) { this.getMoney = getMoney; }}Copy the code
Actual usage. Different calculation rules need to be replaced for different situations of obtaining bounty.
Int sum = 0; BountyCalculater calculater = new BountyCalculater(); calculater.setGetMoney(new BatmanCalculater()); sum += calculater.getBountyMoney(10); calculater.setGetMoney(new HeroMoneyCalculater()); sum += calculater.getBountyMoney(5); calculater.setGetMoney(new DragonCalculater()); sum += calculater.getBountyMoney(1); calculater.setGetMoney(new MonsterCalculater()); sum += calculater.getBountyMoney(34); System.out.println(sum);Copy the code
Now it seems that there are quite a few classes added, which is a disadvantage of the policy pattern. But if you look at the principle of class singleness and the product maintainability phase, you can see the benefits of this strategy pattern.
- Principle of simplicity of classes Each kind of calculation rules are individually encapsulated into a set of calculation methods. Modification of a set of calculation methods does not affect other calculation rules.
- If you want to add a new calculation rule, you simply inherit GetMoney without affecting the other calculation rules.
3.1 Advantages and disadvantages of strategic mode
Advantages: clear structure, simple and intuitive use; Low coupling degree, easy to expand; Disadvantages: As the number of policies increases, so does the number of subclasses of policies.
4. Singleton mode
This is a common pattern. If it is to encapsulate any network request framework or image request framework, this pattern will be used when the entire app only needs a global object. As many blogs have already explained, the whole point of the singleton pattern is to have only one object in the entire program.
4.1 hungry and Hungry mode
/** * Created by Axe on 2017/8/29. * <p> ** * Created by Axe on 2017/8/29. ** ** Created by Axe on 2017/8/29. * 2, in the case of multi-threading, it is not safe to ensure that the object is unique. */ public class HungryModeSingleton { private static final HungryModeSingleton singleton = new HungryModeSingleton(); private HungryModeSingleton() { } public static HungryModeSingleton getInstance() { return singleton; }}Copy the code
4.2 slacker mode
** * Created by Axe on ** ** Created by Axe on ** ** * 2. Lazy mode ensures thread safety * Disadvantages: Public class LazyModeSingleton {private static LazyModeSingleton; private LazyModeSingleton() { } public static synchronized LazyModeSingleton getInstance() { if (singleton == null) { singleton = new LazyModeSingleton(); } return singleton; }}Copy the code
4.3 Two-layer detection channel mode (thread safety)
/** * Created by Axe on 2017/8/29. * <p> * Double Check Lock */ public class DCLSingleton {private static DCLSingleton singleton = null; private DCLSingleton() { } public static DCLSingleton getInstance() { if (singleton == null) { synchronized (DCLSingleton.class) { if (singleton == null) { singleton = new DCLSingleton(); } } } return singleton; }}Copy the code
4.4. Inner class schema
/ * * * Created by Axe on 2017/8/29. * < p > the singleton pattern * * static inner class/public class StaticInnerClassSingleton {private StaticInnerClassSingleton() { } public static StaticInnerClassSingleton getInstance() { return SingletonHolder.singleton; } private static class SingletonHolder { private static final StaticInnerClassSingleton singleton = new StaticInnerClassSingleton(); ##### 4.5 Advantages and disadvantages of the singleton mode: There is only one object in the entire memory, which reduces memory consumption and reduces system performance overhead. Disadvantages: Memory leaks may occur when holding Context; Extensions are difficult and can only be modified by modifying the source code.Copy the code
5. State mode
When you look at state patterns, you think, well, this has to do with states. Continue to use league of Legends as an example:
Now there is such a situation in life, if you want to play league of Legends, the computer must be turned on, the state of the computer is NO, if the computer is not turned on, you can’t play League of Legends, the state of the computer is OFF. If the computer is powered on, the game can be played. If the computer is not powered on, the game cannot be played. If the computer is powered on, the game can be played. Here’s what I wrote when there was no learning state mode:
Public class PlayGameController implements IComputerActivity {/** * private static final int OFF = 0; Private static final int NO = 1; private static final int NO = 1; private int state = 0; public void setSate(int state) { this.state = state; } @override public void playGame() {if (state == OFF) {system.out.println ();} @override public void playGame() {system.out.println (); } else {system.out.println (" playing a game "); }} @override public void watchMovie() {if (state == OFF) {system.out.println (); } else {system.out.println (" watching a movie "); }}}Copy the code
The IComputerActivity behavior interface is defined for computers that temporarily have two methods: playGame and watchMovie. Play games and watch movies must be turned on after the operation, so here in these two methods are added to determine whether the computer is turned on state:
If (state == OFF) {system.out.println (" "); } else {system.out.println (" playing a game "); }Copy the code
This is not a problem when there are fewer states and less computer behavior. But if the computer has more states, this if condition will become tedious. For example, the if judgment will look like this:
If (state == OFF) {system.out.println (" "); } else if(state == XXX){system.out.println (" I am playing a game "); }else if(state == rrr){ } ... . Several if conditions are omitted hereCopy the code
If the computer does more than just play games and watch movies, these if judgments should be written for each behavior. Repeated if judgments are also cumbersome to maintain and more error-prone. So is there a way that these behaviors can be handled individually, that a class only handles one state?
Then use state patterns to refactor the code. 1. Processing of computer startup state:
public class PowerNoState implements IComputerActivity{ @Override public void playGame() { System.out.println(" playing league of Legends "); } @override public void watchMovie() {system.out.println (" watching naruto "); }}Copy the code
2, computer shutdown behavior processing:
/** * state mode: * @author 11373 * */ public class PowerOffState implements IComputerActivity{@override public void PlayGame () {system.out.println (" please start playing the game "); } @override public void watchMovie() {system.out.println (); }}Copy the code
3, and then define the computer power supply
public interface PowerController {
public void powerOn();
public void powerOff();
}
Copy the code
We initialize PowerNoState when we call powerOn and powerOff when we call powerOff
5.1 Advantages and disadvantages of state mode
Advantages: Each state is individually encapsulated into subclasses for easy maintenance and expansion; Can reduce excessive conditional statements, make the structure clearer, improve the maintainability of the code.
Disadvantages: When there are many states, the number of state subclasses must be increased.
6. Observer Mode
If you’ve used RxJava, you’ve been exposed to the Observer mode. Define a dependency on an object, and all objects that depend on it are notified and updated automatically. To take a simple example in the game, in League of Legends, Master Yi is killed wearing resurrection armor, while Galen and Ash are waiting for Master Yi to come back to life before attacking him. So, the observers here are Galen and Ash. One thing they all have in common is the operation of the blow.
/** * @author 11373 ** / public interface Observer {** ** every Observer has an attack method * @param name */ public void hit(String) name); }Copy the code
Master Yi can be observed by others in his state and change his state when it changes.
/** * @author 11373 ** / public interface Obserable {// Public void addObserver(Observer observer); public void removeObserver(Observer observer); // Resurgence method public void Resurgence (String name); }Copy the code
Galen’s realization:
/** * public implements Observer{@override public void hit(String) Name) {system.out.println (" I am Galen, "+name+" resurrection, hit him "); }}Copy the code
Master Yi’s implementation:
/** * master Yi, * * @author 11373 * */ public class YiObserableImpl implements Obserable {private List<Observer> observers = new ArrayList<>(); @Override public void addObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { if (observers.contains(observer)) { observers.remove(observer); } } @Override public void resurgence(String name) { for (Observer observer : observers) { observer.hit(name); }}}Copy the code
Final execution effect:
public static void main(String[] args) { Observer aich = new AichObserverlmpl(); Observer galen = new GaLenObserverImpl(); Obserable yi = new YiObserableImpl(); yi.addObserver(aich); yi.addObserver(galen); Resurgence (" Resurgence "); Resurgence (" Resurgence "); Resurgence (" Resurgence "); }Copy the code
This is Master Esheyi come back to life, hit him I'm Master Galenyi come back to life, hit himCopy the code
6.1 Advantages and disadvantages of the Observer model
Advantages: Observer and observed objects are decoupled, and both dependencies depend on abstractions rather than concrete objects.
Disadvantages: The dependency is not completely removed, the abstract subject still depends on the abstract observer; When using the observer pattern need to consider the development efficiency and operation efficiency, applications include a observer, multiple observers, development, debugging and other content will be more complex, and in Java message notification is generally sequential, so an observer caton, will affect the overall execution efficiency, and in this case, generally USES the asynchronous implementation.
7. Proxy mode
This often happens when playing games. Some people are not very good at playing games, but they are very good at playing games. These are the common proxy patterns.
How do I represent this in code? Define the player interface:
** @author 11373 ** / public interface IPlay {/** ** loginGame(); /** * play a game */ void play(); /** * win the match */ void winGame(); }Copy the code
Define the normal player interface:
/** * game player, * @author 11373 * */ public class GamePlayer implements IPlay{@override public void loginGame() { System.out.println(" game player login game "); } @override public void play() {system.out.println (); } @override public void winGame() {system.out.println (" the game player won the game "); }}Copy the code
Define the calling interface:
/** * @author 11373 ** / public class PlayerProxy implements IPlay {private IPlay player; public void setIPlyer(IPlay player) { this.player = player; } @Override public void loginGame() { player.loginGame(); } @Override public void play() { player.play(); } @Override public void winGame() { player.winGame(); }}Copy the code
Actual operation:
Public static void main(String[] args) {GamePlayer axeChen = new GamePlayer(); GameProxy = new PlayerProxy(); Gameproxy. setIPlyer(axeChen); Gameproxy.logingame (); Gameproxy.play (); // Win the match gameProxy.wingame (); }Copy the code
7.1 Advantages and disadvantages of the proxy mode
The summary of the recommended to see this blog, www.jianshu.com/p/a0e687e09…
8. Adapter mode
Adapter mode can often be seen in Android development, and the setAdapter of RecyclerView is a typical adapter mode, passing in data sources, and then adapting different UI layouts. A simple example to illustrate the adapter mode: for example, in daily life, the power supply of mobile phone is usually 220v, but the power supply of mobile phone is only 5V. This is that we usually have a mobile phone charging adapter to convert 220v voltage to 5V. Now turn this situation into code.
Defining the adapter interface:
public interface Adapter {
public int getVolt5();
}
Copy the code
Power supply entity (actual output power supply) :
public class Power { public int get220v() { return 220; }}Copy the code
Power adapter class, key adaptation operations:
public class PhoneAdapter implements Adapter { private Power power; public PhoneAdapter(Power power) { this.power = power; } @Override public int getVolt5() { return 5; }}Copy the code
Code test:
Power power = new Power(); Println (" power: "+power.get220v()); PhoneAdapter adapter = new PhoneAdapter(power); System.out.println(" Pass is configured after adaptation: "+adapter.getVolt5());Copy the code
Output result:
Power supply voltage: 220 through is configured after adaptation voltage: 5Copy the code
The above code is to convert the input voltage of 220v into 5V through the adapter. The Adapter of RecyclerView is to feed the data source into adapters and then adapt to different layouts. Of course, there’s another class of adapter patterns that I’ll just mention here:
public class PhoneAdapter2 extends Power implements Adapter { @Override public int getVolt5() { Println (" supply voltage: "+get220v()); Println (" adaptor voltage: "+5); system.out.println (" adaptor voltage: "+5); return 5; }}Copy the code
Here, the adapter inherits the data source and implements the interface of the adapter. It has the advantage of not having to hold data source objects, but simply inheriting them.
8.1 Advantages and disadvantages of the adapter mode
Advantages: Improved class reusability, adapters can make a class more versatile; Increased flexibility allows you to change adapters to achieve different results. The adapter can be deleted at any time without affecting the original system.
Disadvantages: Too much use of adapters, will make the system very messy, not easy to grasp the whole. Interface A is called, but interface B is called.
9. Chain of responsibility mode
Explain the chain of responsibility model with an example from your life. For example, an employee of the company bought an office supplies and spent 5000 yuan in total. At this time, the employee went to the department manager for approval of reimbursement. The department manager saw that 5000 yuan was more than he could approve, so he handed it to the director for approval. The director saw that 5000 yuan was more than he could reimburse, so he submitted it to the boss for approval. The boss could reimburse the employee for the amount less than 10W, so the boss approved and agreed to reimburse.
The above is a simple example of the chain of responsibility pattern, which he defines as ****
9.1. Explain reimbursement cases with codes
The similarities of all leaders are abstract, they are reimbursed, there is a range of reimbursements and so on.
Public abstract class Leader {/** * next executor */ public Leader nextHanlder; /** * @return */ public abstract int limit(); /** @money */ public void handle(int money); /** @param money */ public final void handleRequest(int money) {if (money <= limit()) {handle(money); } else { nextHanlder.handleRequest(money); }}}Copy the code
And then the line managers, the directors, the CEOS all implemented these methods.
Public class Manager extends Leader {@override public int limit() {return 1000; } @override public void handle(int money) {system.out.println (" +money "); } } public class CTO extends Leader{ @Override public int limit() { return 5000; } @override public void handle(int money) {system.out.println ("CTO :"+money); } } public class CEO extends Leader{ @Override public int limit() { return 100000; } @override public void handle(int money) {system.out.println (" +money "); }}Copy the code
Final test:
public static void main(String[] args) {
CEO ceo = new CEO();
CTO cto = new CTO();
Manager manager = new Manager();
manager.nextHanlder = cto;
cto.nextHanlder = ceo;
manager.handleRequest(5000);
}
Copy the code
So the result of the execution here is that the manager can’t reimburse, the CTO can reimburse and the CTO reimburses this amount.
CTO is processing the reimbursement amount :5000Copy the code
9.2 Advantages and disadvantages of chain of responsibility mode
Advantages: The relationship between requester and handler is decoupled, and the handler is better extended. Cons: Too many handlers can affect performance, especially when iterating recursively.
10. Prototyping
The core of the prototype pattern is the Clone approach, which involves deep and shallow copy knowledge in Java. Here about the deep and shallow copy, involving what is more, there is direct reference other people’s blogs. www.jianshu.com/p/6d1333917…
Design patterns, reference books: “the Android source code parsing and practical reference blog: www.jianshu.com/p/bf92927c9… Thanks to the blogger April grape’s blog, his blog summary is better, suggest to have a look! I also quote his links in many places. Code address: github.com/AxeChen/Des…